summaryrefslogtreecommitdiff
path: root/src/gallium/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r--src/gallium/drivers/galahad/Makefile11
-rw-r--r--src/gallium/drivers/galahad/SConscript13
-rw-r--r--src/gallium/drivers/galahad/glhd_context.c997
-rw-r--r--src/gallium/drivers/galahad/glhd_context.h64
-rw-r--r--src/gallium/drivers/galahad/glhd_drm.h35
-rw-r--r--src/gallium/drivers/galahad/glhd_objects.c187
-rw-r--r--src/gallium/drivers/galahad/glhd_objects.h175
-rw-r--r--src/gallium/drivers/galahad/glhd_public.h37
-rw-r--r--src/gallium/drivers/galahad/glhd_screen.c330
-rw-r--r--src/gallium/drivers/galahad/glhd_screen.h48
-rw-r--r--src/gallium/drivers/i915/SConscript4
-rw-r--r--src/gallium/drivers/i915/i915_blit.c17
-rw-r--r--src/gallium/drivers/i915/i915_context.h2
-rw-r--r--src/gallium/drivers/i915/i915_debug.c89
-rw-r--r--src/gallium/drivers/i915/i915_debug.h88
-rw-r--r--src/gallium/drivers/i915/i915_debug_fp.c1
-rw-r--r--src/gallium/drivers/i915/i915_debug_private.h45
-rw-r--r--src/gallium/drivers/i915/i915_flush.c5
-rw-r--r--src/gallium/drivers/i915/i915_prim_vbuf.c219
-rw-r--r--src/gallium/drivers/i915/i915_screen.c3
-rw-r--r--src/gallium/drivers/i915/i915_state.h19
-rw-r--r--src/gallium/drivers/i915/i915_state_derived.c79
-rw-r--r--src/gallium/drivers/i915/i915_state_dynamic.c212
-rw-r--r--src/gallium/drivers/i915/i915_state_emit.c17
-rw-r--r--src/gallium/drivers/i915/i915_state_immediate.c91
-rw-r--r--src/gallium/drivers/i915/i915_state_sampler.c113
-rw-r--r--src/gallium/drivers/i965/SConscript4
-rw-r--r--src/gallium/drivers/i965/brw_disasm.c2
-rw-r--r--src/gallium/drivers/i965/brw_pipe_query.c3
-rw-r--r--src/gallium/drivers/identity/id_context.c2
-rw-r--r--src/gallium/drivers/identity/id_objects.c7
-rw-r--r--src/gallium/drivers/identity/id_objects.h1
-rw-r--r--src/gallium/drivers/llvmpipe/.gitignore1
-rw-r--r--src/gallium/drivers/llvmpipe/Makefile2
-rw-r--r--src/gallium/drivers/llvmpipe/SConscript1
-rw-r--r--src/gallium/drivers/llvmpipe/lp_context.c4
-rw-r--r--src/gallium/drivers/llvmpipe/lp_context.h10
-rw-r--r--src/gallium/drivers/llvmpipe/lp_limits.h5
-rw-r--r--src/gallium/drivers/llvmpipe/lp_query.c3
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.c2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup.c11
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_vbuf.c4
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state.h11
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_fs.c126
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_fs.h13
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_gs.c1
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_sampler.c17
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_so.c137
-rw-r--r--src/gallium/drivers/llvmpipe/lp_surface.c32
-rw-r--r--src/gallium/drivers/nv50/nv50_program.c2
-rw-r--r--src/gallium/drivers/nv50/nv50_query.c3
-rw-r--r--src/gallium/drivers/nv50/nv50_surface.c12
-rw-r--r--src/gallium/drivers/nvfx/nvfx_query.c3
-rw-r--r--src/gallium/drivers/nvfx/nvfx_surface.c2
-rw-r--r--src/gallium/drivers/r300/Makefile3
-rw-r--r--src/gallium/drivers/r300/SConscript3
-rw-r--r--src/gallium/drivers/r300/r300_blit.c176
-rw-r--r--src/gallium/drivers/r300/r300_cb.h142
-rw-r--r--src/gallium/drivers/r300/r300_chipset.c7
-rw-r--r--src/gallium/drivers/r300/r300_chipset.h2
-rw-r--r--src/gallium/drivers/r300/r300_context.c264
-rw-r--r--src/gallium/drivers/r300/r300_context.h225
-rw-r--r--src/gallium/drivers/r300/r300_cs.h172
-rw-r--r--src/gallium/drivers/r300/r300_debug.c2
-rw-r--r--src/gallium/drivers/r300/r300_defines.h8
-rw-r--r--src/gallium/drivers/r300/r300_emit.c583
-rw-r--r--src/gallium/drivers/r300/r300_emit.h22
-rw-r--r--src/gallium/drivers/r300/r300_flush.c7
-rw-r--r--src/gallium/drivers/r300/r300_fs.c121
-rw-r--r--src/gallium/drivers/r300/r300_fs.h3
-rw-r--r--src/gallium/drivers/r300/r300_hyperz.c42
-rw-r--r--src/gallium/drivers/r300/r300_query.c178
-rw-r--r--src/gallium/drivers/r300/r300_reg.h63
-rw-r--r--src/gallium/drivers/r300/r300_render.c390
-rw-r--r--src/gallium/drivers/r300/r300_render_stencilref.c158
-rw-r--r--src/gallium/drivers/r300/r300_render_translate.c322
-rw-r--r--src/gallium/drivers/r300/r300_screen.c29
-rw-r--r--src/gallium/drivers/r300/r300_screen.h3
-rw-r--r--src/gallium/drivers/r300/r300_screen_buffer.c41
-rw-r--r--src/gallium/drivers/r300/r300_screen_buffer.h21
-rw-r--r--src/gallium/drivers/r300/r300_state.c582
-rw-r--r--src/gallium/drivers/r300/r300_state.h30
-rw-r--r--src/gallium/drivers/r300/r300_state_derived.c38
-rw-r--r--src/gallium/drivers/r300/r300_state_invariant.c116
-rw-r--r--src/gallium/drivers/r300/r300_state_invariant.h31
-rw-r--r--src/gallium/drivers/r300/r300_texture.c195
-rw-r--r--src/gallium/drivers/r300/r300_texture.h5
-rw-r--r--src/gallium/drivers/r300/r300_tgsi_to_rc.c6
-rw-r--r--src/gallium/drivers/r300/r300_transfer.c62
-rw-r--r--src/gallium/drivers/r300/r300_winsys.h34
-rw-r--r--src/gallium/drivers/r600/r600_blit.c3
-rw-r--r--src/gallium/drivers/r600/r600_helper.c1
-rw-r--r--src/gallium/drivers/r600/r600_query.c2
-rw-r--r--src/gallium/drivers/rbug/rbug_context.c2
-rw-r--r--src/gallium/drivers/softpipe/Makefile1
-rw-r--r--src/gallium/drivers/softpipe/SConscript1
-rw-r--r--src/gallium/drivers/softpipe/sp_context.c31
-rw-r--r--src/gallium/drivers/softpipe/sp_context.h15
-rw-r--r--src/gallium/drivers/softpipe/sp_draw_arrays.c51
-rw-r--r--src/gallium/drivers/softpipe/sp_flush.c3
-rw-r--r--src/gallium/drivers/softpipe/sp_prim_vbuf.c17
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_fs.c8
-rw-r--r--src/gallium/drivers/softpipe/sp_query.c51
-rw-r--r--src/gallium/drivers/softpipe/sp_screen.c2
-rw-r--r--src/gallium/drivers/softpipe/sp_state.h33
-rw-r--r--src/gallium/drivers/softpipe/sp_state_derived.c13
-rw-r--r--src/gallium/drivers/softpipe/sp_state_fs.c3
-rw-r--r--src/gallium/drivers/softpipe/sp_state_sampler.c81
-rw-r--r--src/gallium/drivers/softpipe/sp_state_so.c124
-rw-r--r--src/gallium/drivers/softpipe/sp_surface.c2
-rw-r--r--src/gallium/drivers/softpipe/sp_tex_sample.c2
-rw-r--r--src/gallium/drivers/svga/svga_pipe_query.c5
-rw-r--r--src/gallium/drivers/sw/sw.c1
-rw-r--r--src/gallium/drivers/trace/tr_context.c4
114 files changed, 5856 insertions, 2008 deletions
diff --git a/src/gallium/drivers/galahad/Makefile b/src/gallium/drivers/galahad/Makefile
new file mode 100644
index 0000000000..e9c4f7e28c
--- /dev/null
+++ b/src/gallium/drivers/galahad/Makefile
@@ -0,0 +1,11 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = galahad
+
+C_SOURCES = \
+ glhd_objects.c \
+ glhd_context.c \
+ glhd_screen.c
+
+include ../../Makefile.template
diff --git a/src/gallium/drivers/galahad/SConscript b/src/gallium/drivers/galahad/SConscript
new file mode 100644
index 0000000000..ca6213cfff
--- /dev/null
+++ b/src/gallium/drivers/galahad/SConscript
@@ -0,0 +1,13 @@
+Import('*')
+
+env = env.Clone()
+
+identity = env.ConvenienceLibrary(
+ target = 'identity',
+ source = [
+ 'glhd_context.c',
+ 'glhd_objects.c',
+ 'glhd_screen.c',
+ ])
+
+Export('identity')
diff --git a/src/gallium/drivers/galahad/glhd_context.c b/src/gallium/drivers/galahad/glhd_context.c
new file mode 100644
index 0000000000..ab6f17b3ab
--- /dev/null
+++ b/src/gallium/drivers/galahad/glhd_context.c
@@ -0,0 +1,997 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "pipe/p_context.h"
+
+#include "util/u_format.h"
+#include "util/u_memory.h"
+#include "util/u_inlines.h"
+
+#include "glhd_context.h"
+#include "glhd_objects.h"
+
+
+static void
+galahad_destroy(struct pipe_context *_pipe)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->destroy(pipe);
+
+ FREE(glhd_pipe);
+}
+
+static void
+galahad_draw_arrays(struct pipe_context *_pipe,
+ unsigned prim,
+ unsigned start,
+ unsigned count)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->draw_arrays(pipe,
+ prim,
+ start,
+ count);
+}
+
+static void
+galahad_draw_elements(struct pipe_context *_pipe,
+ struct pipe_resource *_indexResource,
+ unsigned indexSize,
+ int indexBias,
+ unsigned prim,
+ unsigned start,
+ unsigned count)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct galahad_resource *glhd_resource = galahad_resource(_indexResource);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+ struct pipe_resource *indexResource = glhd_resource->resource;
+
+ pipe->draw_elements(pipe,
+ indexResource,
+ indexSize,
+ indexBias,
+ prim,
+ start,
+ count);
+}
+
+static void
+galahad_draw_range_elements(struct pipe_context *_pipe,
+ struct pipe_resource *_indexResource,
+ unsigned indexSize,
+ int indexBias,
+ unsigned minIndex,
+ unsigned maxIndex,
+ unsigned mode,
+ unsigned start,
+ unsigned count)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct galahad_resource *glhd_resource = galahad_resource(_indexResource);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+ struct pipe_resource *indexResource = glhd_resource->resource;
+
+ pipe->draw_range_elements(pipe,
+ indexResource,
+ indexSize,
+ indexBias,
+ minIndex,
+ maxIndex,
+ mode,
+ start,
+ count);
+}
+
+static struct pipe_query *
+galahad_create_query(struct pipe_context *_pipe,
+ unsigned query_type)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ if (query_type == PIPE_QUERY_OCCLUSION_COUNTER &&
+ !pipe->screen->get_param(pipe->screen, PIPE_CAP_OCCLUSION_QUERY)) {
+ glhd_error("Occlusion query requested but not supported");
+ }
+
+ if (query_type == PIPE_QUERY_TIME_ELAPSED &&
+ !pipe->screen->get_param(pipe->screen, PIPE_CAP_TIMER_QUERY)) {
+ glhd_error("Timer query requested but not supported");
+ }
+
+ return pipe->create_query(pipe,
+ query_type);
+}
+
+static void
+galahad_destroy_query(struct pipe_context *_pipe,
+ struct pipe_query *query)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->destroy_query(pipe,
+ query);
+}
+
+static void
+galahad_begin_query(struct pipe_context *_pipe,
+ struct pipe_query *query)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->begin_query(pipe,
+ query);
+}
+
+static void
+galahad_end_query(struct pipe_context *_pipe,
+ struct pipe_query *query)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->end_query(pipe,
+ query);
+}
+
+static boolean
+galahad_get_query_result(struct pipe_context *_pipe,
+ struct pipe_query *query,
+ boolean wait,
+ void *result)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ return pipe->get_query_result(pipe,
+ query,
+ wait,
+ result);
+}
+
+static void *
+galahad_create_blend_state(struct pipe_context *_pipe,
+ const struct pipe_blend_state *blend)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ if (blend->logicop_enable) {
+ if (blend->rt[0].blend_enable) {
+ glhd_warn("Blending enabled for render target 0, but logicops "
+ "are enabled");
+ }
+ }
+
+ return pipe->create_blend_state(pipe,
+ blend);
+}
+
+static void
+galahad_bind_blend_state(struct pipe_context *_pipe,
+ void *blend)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->bind_blend_state(pipe,
+ blend);
+}
+
+static void
+galahad_delete_blend_state(struct pipe_context *_pipe,
+ void *blend)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->delete_blend_state(pipe,
+ blend);
+}
+
+static void *
+galahad_create_sampler_state(struct pipe_context *_pipe,
+ const struct pipe_sampler_state *sampler)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ return pipe->create_sampler_state(pipe,
+ sampler);
+}
+
+static void
+galahad_bind_fragment_sampler_states(struct pipe_context *_pipe,
+ unsigned num_samplers,
+ void **samplers)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->bind_fragment_sampler_states(pipe,
+ num_samplers,
+ samplers);
+}
+
+static void
+galahad_bind_vertex_sampler_states(struct pipe_context *_pipe,
+ unsigned num_samplers,
+ void **samplers)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->bind_vertex_sampler_states(pipe,
+ num_samplers,
+ samplers);
+}
+
+static void
+galahad_delete_sampler_state(struct pipe_context *_pipe,
+ void *sampler)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->delete_sampler_state(pipe,
+ sampler);
+}
+
+static void *
+galahad_create_rasterizer_state(struct pipe_context *_pipe,
+ const struct pipe_rasterizer_state *rasterizer)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ if (rasterizer->point_quad_rasterization) {
+ if (rasterizer->point_smooth) {
+ glhd_warn("Point smoothing requested but ignored");
+ }
+ } else {
+ if (rasterizer->sprite_coord_enable) {
+ glhd_warn("Point sprites requested but ignored");
+ }
+ }
+
+ return pipe->create_rasterizer_state(pipe,
+ rasterizer);
+}
+
+static void
+galahad_bind_rasterizer_state(struct pipe_context *_pipe,
+ void *rasterizer)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->bind_rasterizer_state(pipe,
+ rasterizer);
+}
+
+static void
+galahad_delete_rasterizer_state(struct pipe_context *_pipe,
+ void *rasterizer)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->delete_rasterizer_state(pipe,
+ rasterizer);
+}
+
+static void *
+galahad_create_depth_stencil_alpha_state(struct pipe_context *_pipe,
+ const struct pipe_depth_stencil_alpha_state *depth_stencil_alpha)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ return pipe->create_depth_stencil_alpha_state(pipe,
+ depth_stencil_alpha);
+}
+
+static void
+galahad_bind_depth_stencil_alpha_state(struct pipe_context *_pipe,
+ void *depth_stencil_alpha)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->bind_depth_stencil_alpha_state(pipe,
+ depth_stencil_alpha);
+}
+
+static void
+galahad_delete_depth_stencil_alpha_state(struct pipe_context *_pipe,
+ void *depth_stencil_alpha)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->delete_depth_stencil_alpha_state(pipe,
+ depth_stencil_alpha);
+}
+
+static void *
+galahad_create_fs_state(struct pipe_context *_pipe,
+ const struct pipe_shader_state *fs)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ return pipe->create_fs_state(pipe,
+ fs);
+}
+
+static void
+galahad_bind_fs_state(struct pipe_context *_pipe,
+ void *fs)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->bind_fs_state(pipe,
+ fs);
+}
+
+static void
+galahad_delete_fs_state(struct pipe_context *_pipe,
+ void *fs)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->delete_fs_state(pipe,
+ fs);
+}
+
+static void *
+galahad_create_vs_state(struct pipe_context *_pipe,
+ const struct pipe_shader_state *vs)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ return pipe->create_vs_state(pipe,
+ vs);
+}
+
+static void
+galahad_bind_vs_state(struct pipe_context *_pipe,
+ void *vs)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->bind_vs_state(pipe,
+ vs);
+}
+
+static void
+galahad_delete_vs_state(struct pipe_context *_pipe,
+ void *vs)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->delete_vs_state(pipe,
+ vs);
+}
+
+
+static void *
+galahad_create_vertex_elements_state(struct pipe_context *_pipe,
+ unsigned num_elements,
+ const struct pipe_vertex_element *vertex_elements)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ return pipe->create_vertex_elements_state(pipe,
+ num_elements,
+ vertex_elements);
+}
+
+static void
+galahad_bind_vertex_elements_state(struct pipe_context *_pipe,
+ void *velems)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->bind_vertex_elements_state(pipe,
+ velems);
+}
+
+static void
+galahad_delete_vertex_elements_state(struct pipe_context *_pipe,
+ void *velems)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->delete_vertex_elements_state(pipe,
+ velems);
+}
+
+static void
+galahad_set_blend_color(struct pipe_context *_pipe,
+ const struct pipe_blend_color *blend_color)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->set_blend_color(pipe,
+ blend_color);
+}
+
+static void
+galahad_set_stencil_ref(struct pipe_context *_pipe,
+ const struct pipe_stencil_ref *stencil_ref)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->set_stencil_ref(pipe,
+ stencil_ref);
+}
+
+static void
+galahad_set_clip_state(struct pipe_context *_pipe,
+ const struct pipe_clip_state *clip)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->set_clip_state(pipe,
+ clip);
+}
+
+static void
+galahad_set_sample_mask(struct pipe_context *_pipe,
+ unsigned sample_mask)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->set_sample_mask(pipe,
+ sample_mask);
+}
+
+static void
+galahad_set_constant_buffer(struct pipe_context *_pipe,
+ uint shader,
+ uint index,
+ struct pipe_resource *_resource)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+ struct pipe_resource *unwrapped_resource;
+ struct pipe_resource *resource = NULL;
+
+ /* XXX hmm? unwrap the input state */
+ if (_resource) {
+ unwrapped_resource = galahad_resource_unwrap(_resource);
+ resource = unwrapped_resource;
+ }
+
+ pipe->set_constant_buffer(pipe,
+ shader,
+ index,
+ resource);
+}
+
+static void
+galahad_set_framebuffer_state(struct pipe_context *_pipe,
+ const struct pipe_framebuffer_state *_state)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+ struct pipe_framebuffer_state unwrapped_state;
+ struct pipe_framebuffer_state *state = NULL;
+ unsigned i;
+
+ if (_state->nr_cbufs > PIPE_MAX_COLOR_BUFS) {
+ glhd_error("%d render targets bound, but only %d are permitted by API",
+ _state->nr_cbufs, PIPE_MAX_COLOR_BUFS);
+ } else if (_state->nr_cbufs >
+ pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_RENDER_TARGETS)) {
+ glhd_warn("%d render targets bound, but only %d are supported",
+ _state->nr_cbufs,
+ pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_RENDER_TARGETS));
+ }
+
+ /* unwrap the input state */
+ if (_state) {
+ memcpy(&unwrapped_state, _state, sizeof(unwrapped_state));
+ for(i = 0; i < _state->nr_cbufs; i++)
+ unwrapped_state.cbufs[i] = galahad_surface_unwrap(_state->cbufs[i]);
+ for (; i < PIPE_MAX_COLOR_BUFS; i++)
+ unwrapped_state.cbufs[i] = NULL;
+ unwrapped_state.zsbuf = galahad_surface_unwrap(_state->zsbuf);
+ state = &unwrapped_state;
+ }
+
+ pipe->set_framebuffer_state(pipe,
+ state);
+}
+
+static void
+galahad_set_polygon_stipple(struct pipe_context *_pipe,
+ const struct pipe_poly_stipple *poly_stipple)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->set_polygon_stipple(pipe,
+ poly_stipple);
+}
+
+static void
+galahad_set_scissor_state(struct pipe_context *_pipe,
+ const struct pipe_scissor_state *scissor)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->set_scissor_state(pipe,
+ scissor);
+}
+
+static void
+galahad_set_viewport_state(struct pipe_context *_pipe,
+ const struct pipe_viewport_state *viewport)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->set_viewport_state(pipe,
+ viewport);
+}
+
+static void
+galahad_set_fragment_sampler_views(struct pipe_context *_pipe,
+ unsigned num,
+ struct pipe_sampler_view **_views)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+ struct pipe_sampler_view *unwrapped_views[PIPE_MAX_SAMPLERS];
+ struct pipe_sampler_view **views = NULL;
+ unsigned i;
+
+ if (_views) {
+ for (i = 0; i < num; i++)
+ unwrapped_views[i] = galahad_sampler_view_unwrap(_views[i]);
+ for (; i < PIPE_MAX_SAMPLERS; i++)
+ unwrapped_views[i] = NULL;
+
+ views = unwrapped_views;
+ }
+
+ pipe->set_fragment_sampler_views(pipe, num, views);
+}
+
+static void
+galahad_set_vertex_sampler_views(struct pipe_context *_pipe,
+ unsigned num,
+ struct pipe_sampler_view **_views)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+ struct pipe_sampler_view *unwrapped_views[PIPE_MAX_VERTEX_SAMPLERS];
+ struct pipe_sampler_view **views = NULL;
+ unsigned i;
+
+ if (_views) {
+ for (i = 0; i < num; i++)
+ unwrapped_views[i] = galahad_sampler_view_unwrap(_views[i]);
+ for (; i < PIPE_MAX_VERTEX_SAMPLERS; i++)
+ unwrapped_views[i] = NULL;
+
+ views = unwrapped_views;
+ }
+
+ pipe->set_vertex_sampler_views(pipe, num, views);
+}
+
+static void
+galahad_set_vertex_buffers(struct pipe_context *_pipe,
+ unsigned num_buffers,
+ const struct pipe_vertex_buffer *_buffers)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+ struct pipe_vertex_buffer unwrapped_buffers[PIPE_MAX_SHADER_INPUTS];
+ struct pipe_vertex_buffer *buffers = NULL;
+ unsigned i;
+
+ if (num_buffers) {
+ memcpy(unwrapped_buffers, _buffers, num_buffers * sizeof(*_buffers));
+ for (i = 0; i < num_buffers; i++)
+ unwrapped_buffers[i].buffer = galahad_resource_unwrap(_buffers[i].buffer);
+ buffers = unwrapped_buffers;
+ }
+
+ pipe->set_vertex_buffers(pipe,
+ num_buffers,
+ buffers);
+}
+static void
+galahad_resource_copy_region(struct pipe_context *_pipe,
+ struct pipe_resource *_dst,
+ struct pipe_subresource subdst,
+ unsigned dstx,
+ unsigned dsty,
+ unsigned dstz,
+ struct pipe_resource *_src,
+ struct pipe_subresource subsrc,
+ unsigned srcx,
+ unsigned srcy,
+ unsigned srcz,
+ unsigned width,
+ unsigned height)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct galahad_resource *glhd_resource_dst = galahad_resource(_dst);
+ struct galahad_resource *glhd_resource_src = galahad_resource(_src);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+ struct pipe_resource *dst = glhd_resource_dst->resource;
+ struct pipe_resource *src = glhd_resource_src->resource;
+
+ if (_dst->format != _src->format) {
+ glhd_warn("Format mismatch: Source is %s, destination is %s",
+ util_format_short_name(_src->format),
+ util_format_short_name(_dst->format));
+ }
+
+ pipe->resource_copy_region(pipe,
+ dst,
+ subdst,
+ dstx,
+ dsty,
+ dstz,
+ src,
+ subsrc,
+ srcx,
+ srcy,
+ srcz,
+ width,
+ height);
+}
+
+static void
+galahad_clear(struct pipe_context *_pipe,
+ unsigned buffers,
+ const float *rgba,
+ double depth,
+ unsigned stencil)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->clear(pipe,
+ buffers,
+ rgba,
+ depth,
+ stencil);
+}
+
+static void
+galahad_clear_render_target(struct pipe_context *_pipe,
+ struct pipe_surface *_dst,
+ const float *rgba,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct galahad_surface *glhd_surface_dst = galahad_surface(_dst);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+ struct pipe_surface *dst = glhd_surface_dst->surface;
+
+ pipe->clear_render_target(pipe,
+ dst,
+ rgba,
+ dstx,
+ dsty,
+ width,
+ height);
+}
+static void
+galahad_clear_depth_stencil(struct pipe_context *_pipe,
+ struct pipe_surface *_dst,
+ unsigned clear_flags,
+ double depth,
+ unsigned stencil,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct galahad_surface *glhd_surface_dst = galahad_surface(_dst);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+ struct pipe_surface *dst = glhd_surface_dst->surface;
+
+ pipe->clear_depth_stencil(pipe,
+ dst,
+ clear_flags,
+ depth,
+ stencil,
+ dstx,
+ dsty,
+ width,
+ height);
+
+}
+
+static void
+galahad_flush(struct pipe_context *_pipe,
+ unsigned flags,
+ struct pipe_fence_handle **fence)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+
+ pipe->flush(pipe,
+ flags,
+ fence);
+}
+
+static unsigned int
+galahad_is_resource_referenced(struct pipe_context *_pipe,
+ struct pipe_resource *_resource,
+ unsigned face,
+ unsigned level)
+{
+ struct galahad_context *glhd_pipe = galahad_context(_pipe);
+ struct galahad_resource *glhd_resource = galahad_resource(_resource);
+ struct pipe_context *pipe = glhd_pipe->pipe;
+ struct pipe_resource *resource = glhd_resource->resource;
+
+ return pipe->is_resource_referenced(pipe,
+ resource,
+ face,
+ level);
+}
+
+static struct pipe_sampler_view *
+galahad_context_create_sampler_view(struct pipe_context *_pipe,
+ struct pipe_resource *_resource,
+ const struct pipe_sampler_view *templ)
+{
+ struct galahad_context *glhd_context = galahad_context(_pipe);
+ struct galahad_resource *glhd_resource = galahad_resource(_resource);
+ struct pipe_context *pipe = glhd_context->pipe;
+ struct pipe_resource *resource = glhd_resource->resource;
+ struct pipe_sampler_view *result;
+
+ result = pipe->create_sampler_view(pipe,
+ resource,
+ templ);
+
+ if (result)
+ return galahad_sampler_view_create(glhd_context, glhd_resource, result);
+ return NULL;
+}
+
+static void
+galahad_context_sampler_view_destroy(struct pipe_context *_pipe,
+ struct pipe_sampler_view *_view)
+{
+ galahad_sampler_view_destroy(galahad_context(_pipe),
+ galahad_sampler_view(_view));
+}
+
+static struct pipe_transfer *
+galahad_context_get_transfer(struct pipe_context *_context,
+ struct pipe_resource *_resource,
+ struct pipe_subresource sr,
+ unsigned usage,
+ const struct pipe_box *box)
+{
+ struct galahad_context *glhd_context = galahad_context(_context);
+ struct galahad_resource *glhd_resource = galahad_resource(_resource);
+ struct pipe_context *context = glhd_context->pipe;
+ struct pipe_resource *resource = glhd_resource->resource;
+ struct pipe_transfer *result;
+
+ result = context->get_transfer(context,
+ resource,
+ sr,
+ usage,
+ box);
+
+ if (result)
+ return galahad_transfer_create(glhd_context, glhd_resource, result);
+ return NULL;
+}
+
+static void
+galahad_context_transfer_destroy(struct pipe_context *_pipe,
+ struct pipe_transfer *_transfer)
+{
+ galahad_transfer_destroy(galahad_context(_pipe),
+ galahad_transfer(_transfer));
+}
+
+static void *
+galahad_context_transfer_map(struct pipe_context *_context,
+ struct pipe_transfer *_transfer)
+{
+ struct galahad_context *glhd_context = galahad_context(_context);
+ struct galahad_transfer *glhd_transfer = galahad_transfer(_transfer);
+ struct pipe_context *context = glhd_context->pipe;
+ struct pipe_transfer *transfer = glhd_transfer->transfer;
+
+ return context->transfer_map(context,
+ transfer);
+}
+
+
+
+static void
+galahad_context_transfer_flush_region(struct pipe_context *_context,
+ struct pipe_transfer *_transfer,
+ const struct pipe_box *box)
+{
+ struct galahad_context *glhd_context = galahad_context(_context);
+ struct galahad_transfer *glhd_transfer = galahad_transfer(_transfer);
+ struct pipe_context *context = glhd_context->pipe;
+ struct pipe_transfer *transfer = glhd_transfer->transfer;
+
+ context->transfer_flush_region(context,
+ transfer,
+ box);
+}
+
+
+static void
+galahad_context_transfer_unmap(struct pipe_context *_context,
+ struct pipe_transfer *_transfer)
+{
+ struct galahad_context *glhd_context = galahad_context(_context);
+ struct galahad_transfer *glhd_transfer = galahad_transfer(_transfer);
+ struct pipe_context *context = glhd_context->pipe;
+ struct pipe_transfer *transfer = glhd_transfer->transfer;
+
+ context->transfer_unmap(context,
+ transfer);
+}
+
+
+static void
+galahad_context_transfer_inline_write(struct pipe_context *_context,
+ struct pipe_resource *_resource,
+ struct pipe_subresource sr,
+ unsigned usage,
+ const struct pipe_box *box,
+ const void *data,
+ unsigned stride,
+ unsigned slice_stride)
+{
+ struct galahad_context *glhd_context = galahad_context(_context);
+ struct galahad_resource *glhd_resource = galahad_resource(_resource);
+ struct pipe_context *context = glhd_context->pipe;
+ struct pipe_resource *resource = glhd_resource->resource;
+
+ context->transfer_inline_write(context,
+ resource,
+ sr,
+ usage,
+ box,
+ data,
+ stride,
+ slice_stride);
+}
+
+
+struct pipe_context *
+galahad_context_create(struct pipe_screen *_screen, struct pipe_context *pipe)
+{
+ struct galahad_context *glhd_pipe;
+ (void)galahad_screen(_screen);
+
+ glhd_pipe = CALLOC_STRUCT(galahad_context);
+ if (!glhd_pipe) {
+ return NULL;
+ }
+
+ glhd_pipe->base.winsys = NULL;
+ glhd_pipe->base.screen = _screen;
+ glhd_pipe->base.priv = pipe->priv; /* expose wrapped data */
+ glhd_pipe->base.draw = NULL;
+
+ glhd_pipe->base.destroy = galahad_destroy;
+ glhd_pipe->base.draw_arrays = galahad_draw_arrays;
+ glhd_pipe->base.draw_elements = galahad_draw_elements;
+ glhd_pipe->base.draw_range_elements = galahad_draw_range_elements;
+ glhd_pipe->base.create_query = galahad_create_query;
+ glhd_pipe->base.destroy_query = galahad_destroy_query;
+ glhd_pipe->base.begin_query = galahad_begin_query;
+ glhd_pipe->base.end_query = galahad_end_query;
+ glhd_pipe->base.get_query_result = galahad_get_query_result;
+ glhd_pipe->base.create_blend_state = galahad_create_blend_state;
+ glhd_pipe->base.bind_blend_state = galahad_bind_blend_state;
+ glhd_pipe->base.delete_blend_state = galahad_delete_blend_state;
+ glhd_pipe->base.create_sampler_state = galahad_create_sampler_state;
+ glhd_pipe->base.bind_fragment_sampler_states = galahad_bind_fragment_sampler_states;
+ glhd_pipe->base.bind_vertex_sampler_states = galahad_bind_vertex_sampler_states;
+ glhd_pipe->base.delete_sampler_state = galahad_delete_sampler_state;
+ glhd_pipe->base.create_rasterizer_state = galahad_create_rasterizer_state;
+ glhd_pipe->base.bind_rasterizer_state = galahad_bind_rasterizer_state;
+ glhd_pipe->base.delete_rasterizer_state = galahad_delete_rasterizer_state;
+ glhd_pipe->base.create_depth_stencil_alpha_state = galahad_create_depth_stencil_alpha_state;
+ glhd_pipe->base.bind_depth_stencil_alpha_state = galahad_bind_depth_stencil_alpha_state;
+ glhd_pipe->base.delete_depth_stencil_alpha_state = galahad_delete_depth_stencil_alpha_state;
+ glhd_pipe->base.create_fs_state = galahad_create_fs_state;
+ glhd_pipe->base.bind_fs_state = galahad_bind_fs_state;
+ glhd_pipe->base.delete_fs_state = galahad_delete_fs_state;
+ glhd_pipe->base.create_vs_state = galahad_create_vs_state;
+ glhd_pipe->base.bind_vs_state = galahad_bind_vs_state;
+ glhd_pipe->base.delete_vs_state = galahad_delete_vs_state;
+ glhd_pipe->base.create_vertex_elements_state = galahad_create_vertex_elements_state;
+ glhd_pipe->base.bind_vertex_elements_state = galahad_bind_vertex_elements_state;
+ glhd_pipe->base.delete_vertex_elements_state = galahad_delete_vertex_elements_state;
+ glhd_pipe->base.set_blend_color = galahad_set_blend_color;
+ glhd_pipe->base.set_stencil_ref = galahad_set_stencil_ref;
+ glhd_pipe->base.set_clip_state = galahad_set_clip_state;
+ glhd_pipe->base.set_sample_mask = galahad_set_sample_mask;
+ glhd_pipe->base.set_constant_buffer = galahad_set_constant_buffer;
+ glhd_pipe->base.set_framebuffer_state = galahad_set_framebuffer_state;
+ glhd_pipe->base.set_polygon_stipple = galahad_set_polygon_stipple;
+ glhd_pipe->base.set_scissor_state = galahad_set_scissor_state;
+ glhd_pipe->base.set_viewport_state = galahad_set_viewport_state;
+ glhd_pipe->base.set_fragment_sampler_views = galahad_set_fragment_sampler_views;
+ glhd_pipe->base.set_vertex_sampler_views = galahad_set_vertex_sampler_views;
+ glhd_pipe->base.set_vertex_buffers = galahad_set_vertex_buffers;
+ glhd_pipe->base.resource_copy_region = galahad_resource_copy_region;
+ glhd_pipe->base.clear = galahad_clear;
+ glhd_pipe->base.clear_render_target = galahad_clear_render_target;
+ glhd_pipe->base.clear_depth_stencil = galahad_clear_depth_stencil;
+ glhd_pipe->base.flush = galahad_flush;
+ glhd_pipe->base.is_resource_referenced = galahad_is_resource_referenced;
+ glhd_pipe->base.create_sampler_view = galahad_context_create_sampler_view;
+ glhd_pipe->base.sampler_view_destroy = galahad_context_sampler_view_destroy;
+ glhd_pipe->base.get_transfer = galahad_context_get_transfer;
+ glhd_pipe->base.transfer_destroy = galahad_context_transfer_destroy;
+ glhd_pipe->base.transfer_map = galahad_context_transfer_map;
+ glhd_pipe->base.transfer_unmap = galahad_context_transfer_unmap;
+ glhd_pipe->base.transfer_flush_region = galahad_context_transfer_flush_region;
+ glhd_pipe->base.transfer_inline_write = galahad_context_transfer_inline_write;
+
+ glhd_pipe->pipe = pipe;
+
+ return &glhd_pipe->base;
+}
diff --git a/src/gallium/drivers/galahad/glhd_context.h b/src/gallium/drivers/galahad/glhd_context.h
new file mode 100644
index 0000000000..4e71753ac3
--- /dev/null
+++ b/src/gallium/drivers/galahad/glhd_context.h
@@ -0,0 +1,64 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef GLHD_CONTEXT_H
+#define GLHD_CONTEXT_H
+
+#include <stdio.h>
+
+#include "pipe/p_state.h"
+#include "pipe/p_context.h"
+
+
+struct galahad_context {
+ struct pipe_context base; /**< base class */
+
+ struct pipe_context *pipe;
+};
+
+
+struct pipe_context *
+galahad_context_create(struct pipe_screen *screen, struct pipe_context *pipe);
+
+
+static INLINE struct galahad_context *
+galahad_context(struct pipe_context *pipe)
+{
+ return (struct galahad_context *)pipe;
+}
+
+#define glhd_warn(...) \
+do { \
+ fprintf(stderr, "galahad: %s: ", __FUNCTION__); \
+ fprintf(stderr, __VA_ARGS__); \
+ fprintf(stderr, "\n"); \
+} while (0)
+
+#define glhd_error(...) \
+ glhd_warn(__VA_ARGS__);
+
+#endif /* GLHD_CONTEXT_H */
diff --git a/src/gallium/drivers/galahad/glhd_drm.h b/src/gallium/drivers/galahad/glhd_drm.h
new file mode 100644
index 0000000000..613ac24946
--- /dev/null
+++ b/src/gallium/drivers/galahad/glhd_drm.h
@@ -0,0 +1,35 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef GLHD_DRM_H
+#define GLHD_DRM_H
+
+struct drm_api;
+
+struct drm_api* galahad_drm_create(struct drm_api *api);
+
+#endif /* GLHD_DRM_H */
diff --git a/src/gallium/drivers/galahad/glhd_objects.c b/src/gallium/drivers/galahad/glhd_objects.c
new file mode 100644
index 0000000000..6c5a21ae70
--- /dev/null
+++ b/src/gallium/drivers/galahad/glhd_objects.c
@@ -0,0 +1,187 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_inlines.h"
+#include "util/u_memory.h"
+
+#include "glhd_screen.h"
+#include "glhd_objects.h"
+#include "glhd_context.h"
+
+
+
+struct pipe_resource *
+galahad_resource_create(struct galahad_screen *glhd_screen,
+ struct pipe_resource *resource)
+{
+ struct galahad_resource *glhd_resource;
+
+ if(!resource)
+ goto error;
+
+ assert(resource->screen == glhd_screen->screen);
+
+ glhd_resource = CALLOC_STRUCT(galahad_resource);
+ if(!glhd_resource)
+ goto error;
+
+ memcpy(&glhd_resource->base, resource, sizeof(struct pipe_resource));
+
+ pipe_reference_init(&glhd_resource->base.reference, 1);
+ glhd_resource->base.screen = &glhd_screen->base;
+ glhd_resource->resource = resource;
+
+ return &glhd_resource->base;
+
+error:
+ pipe_resource_reference(&resource, NULL);
+ return NULL;
+}
+
+void
+galahad_resource_destroy(struct galahad_resource *glhd_resource)
+{
+ pipe_resource_reference(&glhd_resource->resource, NULL);
+ FREE(glhd_resource);
+}
+
+
+struct pipe_surface *
+galahad_surface_create(struct galahad_resource *glhd_resource,
+ struct pipe_surface *surface)
+{
+ struct galahad_surface *glhd_surface;
+
+ if(!surface)
+ goto error;
+
+ assert(surface->texture == glhd_resource->resource);
+
+ glhd_surface = CALLOC_STRUCT(galahad_surface);
+ if(!glhd_surface)
+ goto error;
+
+ memcpy(&glhd_surface->base, surface, sizeof(struct pipe_surface));
+
+ pipe_reference_init(&glhd_surface->base.reference, 1);
+ glhd_surface->base.texture = NULL;
+ pipe_resource_reference(&glhd_surface->base.texture, &glhd_resource->base);
+ glhd_surface->surface = surface;
+
+ return &glhd_surface->base;
+
+error:
+ pipe_surface_reference(&surface, NULL);
+ return NULL;
+}
+
+void
+galahad_surface_destroy(struct galahad_surface *glhd_surface)
+{
+ pipe_resource_reference(&glhd_surface->base.texture, NULL);
+ pipe_surface_reference(&glhd_surface->surface, NULL);
+ FREE(glhd_surface);
+}
+
+
+struct pipe_sampler_view *
+galahad_sampler_view_create(struct galahad_context *glhd_context,
+ struct galahad_resource *glhd_resource,
+ struct pipe_sampler_view *view)
+{
+ struct galahad_sampler_view *glhd_view;
+
+ if (!view)
+ goto error;
+
+ assert(view->texture == glhd_resource->resource);
+
+ glhd_view = CALLOC_STRUCT(galahad_sampler_view);
+
+ glhd_view->base = *view;
+ glhd_view->base.reference.count = 1;
+ glhd_view->base.texture = NULL;
+ pipe_resource_reference(&glhd_view->base.texture, glhd_resource->resource);
+ glhd_view->base.context = glhd_context->pipe;
+ glhd_view->sampler_view = view;
+
+ return &glhd_view->base;
+error:
+ return NULL;
+}
+
+void
+galahad_sampler_view_destroy(struct galahad_context *glhd_context,
+ struct galahad_sampler_view *glhd_view)
+{
+ pipe_resource_reference(&glhd_view->base.texture, NULL);
+ glhd_context->pipe->sampler_view_destroy(glhd_context->pipe,
+ glhd_view->sampler_view);
+ FREE(glhd_view);
+}
+
+
+struct pipe_transfer *
+galahad_transfer_create(struct galahad_context *glhd_context,
+ struct galahad_resource *glhd_resource,
+ struct pipe_transfer *transfer)
+{
+ struct galahad_transfer *glhd_transfer;
+
+ if(!transfer)
+ goto error;
+
+ assert(transfer->resource == glhd_resource->resource);
+
+ glhd_transfer = CALLOC_STRUCT(galahad_transfer);
+ if(!glhd_transfer)
+ goto error;
+
+ memcpy(&glhd_transfer->base, transfer, sizeof(struct pipe_transfer));
+
+ glhd_transfer->base.resource = NULL;
+ glhd_transfer->transfer = transfer;
+
+ pipe_resource_reference(&glhd_transfer->base.resource, &glhd_resource->base);
+ assert(glhd_transfer->base.resource == &glhd_resource->base);
+
+ return &glhd_transfer->base;
+
+error:
+ glhd_context->pipe->transfer_destroy(glhd_context->pipe, transfer);
+ return NULL;
+}
+
+void
+galahad_transfer_destroy(struct galahad_context *glhd_context,
+ struct galahad_transfer *glhd_transfer)
+{
+ pipe_resource_reference(&glhd_transfer->base.resource, NULL);
+ glhd_context->pipe->transfer_destroy(glhd_context->pipe,
+ glhd_transfer->transfer);
+ FREE(glhd_transfer);
+}
diff --git a/src/gallium/drivers/galahad/glhd_objects.h b/src/gallium/drivers/galahad/glhd_objects.h
new file mode 100644
index 0000000000..935803915d
--- /dev/null
+++ b/src/gallium/drivers/galahad/glhd_objects.h
@@ -0,0 +1,175 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef GLHD_OBJECTS_H
+#define GLHD_OBJECTS_H
+
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_state.h"
+
+#include "glhd_screen.h"
+
+struct galahad_context;
+
+
+struct galahad_resource
+{
+ struct pipe_resource base;
+
+ struct pipe_resource *resource;
+};
+
+
+struct galahad_sampler_view
+{
+ struct pipe_sampler_view base;
+
+ struct pipe_sampler_view *sampler_view;
+};
+
+
+struct galahad_surface
+{
+ struct pipe_surface base;
+
+ struct pipe_surface *surface;
+};
+
+
+struct galahad_transfer
+{
+ struct pipe_transfer base;
+
+ struct pipe_transfer *transfer;
+};
+
+
+static INLINE struct galahad_resource *
+galahad_resource(struct pipe_resource *_resource)
+{
+ if(!_resource)
+ return NULL;
+ (void)galahad_screen(_resource->screen);
+ return (struct galahad_resource *)_resource;
+}
+
+static INLINE struct galahad_sampler_view *
+galahad_sampler_view(struct pipe_sampler_view *_sampler_view)
+{
+ if (!_sampler_view) {
+ return NULL;
+ }
+ return (struct galahad_sampler_view *)_sampler_view;
+}
+
+static INLINE struct galahad_surface *
+galahad_surface(struct pipe_surface *_surface)
+{
+ if(!_surface)
+ return NULL;
+ (void)galahad_resource(_surface->texture);
+ return (struct galahad_surface *)_surface;
+}
+
+static INLINE struct galahad_transfer *
+galahad_transfer(struct pipe_transfer *_transfer)
+{
+ if(!_transfer)
+ return NULL;
+ (void)galahad_resource(_transfer->resource);
+ return (struct galahad_transfer *)_transfer;
+}
+
+static INLINE struct pipe_resource *
+galahad_resource_unwrap(struct pipe_resource *_resource)
+{
+ if(!_resource)
+ return NULL;
+ return galahad_resource(_resource)->resource;
+}
+
+static INLINE struct pipe_sampler_view *
+galahad_sampler_view_unwrap(struct pipe_sampler_view *_sampler_view)
+{
+ if (!_sampler_view) {
+ return NULL;
+ }
+ return galahad_sampler_view(_sampler_view)->sampler_view;
+}
+
+static INLINE struct pipe_surface *
+galahad_surface_unwrap(struct pipe_surface *_surface)
+{
+ if(!_surface)
+ return NULL;
+ return galahad_surface(_surface)->surface;
+}
+
+static INLINE struct pipe_transfer *
+galahad_transfer_unwrap(struct pipe_transfer *_transfer)
+{
+ if(!_transfer)
+ return NULL;
+ return galahad_transfer(_transfer)->transfer;
+}
+
+
+struct pipe_resource *
+galahad_resource_create(struct galahad_screen *glhd_screen,
+ struct pipe_resource *resource);
+
+void
+galahad_resource_destroy(struct galahad_resource *glhd_resource);
+
+struct pipe_surface *
+galahad_surface_create(struct galahad_resource *glhd_resource,
+ struct pipe_surface *surface);
+
+void
+galahad_surface_destroy(struct galahad_surface *glhd_surface);
+
+struct pipe_sampler_view *
+galahad_sampler_view_create(struct galahad_context *glhd_context,
+ struct galahad_resource *glhd_resource,
+ struct pipe_sampler_view *view);
+
+void
+galahad_sampler_view_destroy(struct galahad_context *glhd_context,
+ struct galahad_sampler_view *glhd_sampler_view);
+
+struct pipe_transfer *
+galahad_transfer_create(struct galahad_context *glhd_context,
+ struct galahad_resource *glhd_resource,
+ struct pipe_transfer *transfer);
+
+void
+galahad_transfer_destroy(struct galahad_context *glhd_context,
+ struct galahad_transfer *glhd_transfer);
+
+
+#endif /* GLHD_OBJECTS_H */
diff --git a/src/gallium/drivers/galahad/glhd_public.h b/src/gallium/drivers/galahad/glhd_public.h
new file mode 100644
index 0000000000..77a380196a
--- /dev/null
+++ b/src/gallium/drivers/galahad/glhd_public.h
@@ -0,0 +1,37 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef GLHD_PUBLIC_H
+#define GLHD_PUBLIC_H
+
+struct pipe_screen;
+struct pipe_context;
+
+struct pipe_screen *
+galahad_screen_create(struct pipe_screen *screen);
+
+#endif /* GLHD_PUBLIC_H */
diff --git a/src/gallium/drivers/galahad/glhd_screen.c b/src/gallium/drivers/galahad/glhd_screen.c
new file mode 100644
index 0000000000..bcc37cb633
--- /dev/null
+++ b/src/gallium/drivers/galahad/glhd_screen.c
@@ -0,0 +1,330 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * 2010 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "pipe/p_screen.h"
+#include "pipe/p_state.h"
+#include "util/u_memory.h"
+
+#include "glhd_public.h"
+#include "glhd_screen.h"
+#include "glhd_context.h"
+#include "glhd_objects.h"
+
+
+static void
+galahad_screen_destroy(struct pipe_screen *_screen)
+{
+ struct galahad_screen *glhd_screen = galahad_screen(_screen);
+ struct pipe_screen *screen = glhd_screen->screen;
+
+ screen->destroy(screen);
+
+ FREE(glhd_screen);
+}
+
+static const char *
+galahad_screen_get_name(struct pipe_screen *_screen)
+{
+ struct galahad_screen *glhd_screen = galahad_screen(_screen);
+ struct pipe_screen *screen = glhd_screen->screen;
+
+ return screen->get_name(screen);
+}
+
+static const char *
+galahad_screen_get_vendor(struct pipe_screen *_screen)
+{
+ struct galahad_screen *glhd_screen = galahad_screen(_screen);
+ struct pipe_screen *screen = glhd_screen->screen;
+
+ return screen->get_vendor(screen);
+}
+
+static int
+galahad_screen_get_param(struct pipe_screen *_screen,
+ enum pipe_cap param)
+{
+ struct galahad_screen *glhd_screen = galahad_screen(_screen);
+ struct pipe_screen *screen = glhd_screen->screen;
+
+ return screen->get_param(screen,
+ param);
+}
+
+static float
+galahad_screen_get_paramf(struct pipe_screen *_screen,
+ enum pipe_cap param)
+{
+ struct galahad_screen *glhd_screen = galahad_screen(_screen);
+ struct pipe_screen *screen = glhd_screen->screen;
+
+ return screen->get_paramf(screen,
+ param);
+}
+
+static boolean
+galahad_screen_is_format_supported(struct pipe_screen *_screen,
+ enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned sample_count,
+ unsigned tex_usage,
+ unsigned geom_flags)
+{
+ struct galahad_screen *glhd_screen = galahad_screen(_screen);
+ struct pipe_screen *screen = glhd_screen->screen;
+
+ if (target >= PIPE_MAX_TEXTURE_TYPES) {
+ glhd_warn("Received bogus texture target %d", target);
+ }
+
+ return screen->is_format_supported(screen,
+ format,
+ target,
+ sample_count,
+ tex_usage,
+ geom_flags);
+}
+
+static struct pipe_context *
+galahad_screen_context_create(struct pipe_screen *_screen,
+ void *priv)
+{
+ struct galahad_screen *glhd_screen = galahad_screen(_screen);
+ struct pipe_screen *screen = glhd_screen->screen;
+ struct pipe_context *result;
+
+ result = screen->context_create(screen, priv);
+ if (result)
+ return galahad_context_create(_screen, result);
+ return NULL;
+}
+
+static struct pipe_resource *
+galahad_screen_resource_create(struct pipe_screen *_screen,
+ const struct pipe_resource *templat)
+{
+ struct galahad_screen *glhd_screen = galahad_screen(_screen);
+ struct pipe_screen *screen = glhd_screen->screen;
+ struct pipe_resource *result;
+
+ result = screen->resource_create(screen,
+ templat);
+
+ if (result)
+ return galahad_resource_create(glhd_screen, result);
+ return NULL;
+}
+
+static struct pipe_resource *
+galahad_screen_resource_from_handle(struct pipe_screen *_screen,
+ const struct pipe_resource *templ,
+ struct winsys_handle *handle)
+{
+ struct galahad_screen *glhd_screen = galahad_screen(_screen);
+ struct pipe_screen *screen = glhd_screen->screen;
+ struct pipe_resource *result;
+
+ /* TODO trace call */
+
+ result = screen->resource_from_handle(screen, templ, handle);
+
+ result = galahad_resource_create(galahad_screen(_screen), result);
+
+ return result;
+}
+
+static boolean
+galahad_screen_resource_get_handle(struct pipe_screen *_screen,
+ struct pipe_resource *_resource,
+ struct winsys_handle *handle)
+{
+ struct galahad_screen *glhd_screen = galahad_screen(_screen);
+ struct galahad_resource *glhd_resource = galahad_resource(_resource);
+ struct pipe_screen *screen = glhd_screen->screen;
+ struct pipe_resource *resource = glhd_resource->resource;
+
+ /* TODO trace call */
+
+ return screen->resource_get_handle(screen, resource, handle);
+}
+
+
+
+static void
+galahad_screen_resource_destroy(struct pipe_screen *screen,
+ struct pipe_resource *_resource)
+{
+ galahad_resource_destroy(galahad_resource(_resource));
+}
+
+static struct pipe_surface *
+galahad_screen_get_tex_surface(struct pipe_screen *_screen,
+ struct pipe_resource *_resource,
+ unsigned face,
+ unsigned level,
+ unsigned zslice,
+ unsigned usage)
+{
+ struct galahad_screen *glhd_screen = galahad_screen(_screen);
+ struct galahad_resource *glhd_resource = galahad_resource(_resource);
+ struct pipe_screen *screen = glhd_screen->screen;
+ struct pipe_resource *resource = glhd_resource->resource;
+ struct pipe_surface *result;
+
+ result = screen->get_tex_surface(screen,
+ resource,
+ face,
+ level,
+ zslice,
+ usage);
+
+ if (result)
+ return galahad_surface_create(glhd_resource, result);
+ return NULL;
+}
+
+static void
+galahad_screen_tex_surface_destroy(struct pipe_surface *_surface)
+{
+ galahad_surface_destroy(galahad_surface(_surface));
+}
+
+
+
+static struct pipe_resource *
+galahad_screen_user_buffer_create(struct pipe_screen *_screen,
+ void *ptr,
+ unsigned bytes,
+ unsigned usage)
+{
+ struct galahad_screen *glhd_screen = galahad_screen(_screen);
+ struct pipe_screen *screen = glhd_screen->screen;
+ struct pipe_resource *result;
+
+ result = screen->user_buffer_create(screen,
+ ptr,
+ bytes,
+ usage);
+
+ if (result)
+ return galahad_resource_create(glhd_screen, result);
+ return NULL;
+}
+
+
+
+static void
+galahad_screen_flush_frontbuffer(struct pipe_screen *_screen,
+ struct pipe_surface *_surface,
+ void *context_private)
+{
+ struct galahad_screen *glhd_screen = galahad_screen(_screen);
+ struct galahad_surface *glhd_surface = galahad_surface(_surface);
+ struct pipe_screen *screen = glhd_screen->screen;
+ struct pipe_surface *surface = glhd_surface->surface;
+
+ screen->flush_frontbuffer(screen,
+ surface,
+ context_private);
+}
+
+static void
+galahad_screen_fence_reference(struct pipe_screen *_screen,
+ struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *fence)
+{
+ struct galahad_screen *glhd_screen = galahad_screen(_screen);
+ struct pipe_screen *screen = glhd_screen->screen;
+
+ screen->fence_reference(screen,
+ ptr,
+ fence);
+}
+
+static int
+galahad_screen_fence_signalled(struct pipe_screen *_screen,
+ struct pipe_fence_handle *fence,
+ unsigned flags)
+{
+ struct galahad_screen *glhd_screen = galahad_screen(_screen);
+ struct pipe_screen *screen = glhd_screen->screen;
+
+ return screen->fence_signalled(screen,
+ fence,
+ flags);
+}
+
+static int
+galahad_screen_fence_finish(struct pipe_screen *_screen,
+ struct pipe_fence_handle *fence,
+ unsigned flags)
+{
+ struct galahad_screen *glhd_screen = galahad_screen(_screen);
+ struct pipe_screen *screen = glhd_screen->screen;
+
+ return screen->fence_finish(screen,
+ fence,
+ flags);
+}
+
+struct pipe_screen *
+galahad_screen_create(struct pipe_screen *screen)
+{
+ struct galahad_screen *glhd_screen;
+
+ glhd_screen = CALLOC_STRUCT(galahad_screen);
+ if (!glhd_screen) {
+ return NULL;
+ }
+
+ glhd_screen->base.winsys = NULL;
+
+ glhd_screen->base.destroy = galahad_screen_destroy;
+ glhd_screen->base.get_name = galahad_screen_get_name;
+ glhd_screen->base.get_vendor = galahad_screen_get_vendor;
+ glhd_screen->base.get_param = galahad_screen_get_param;
+ glhd_screen->base.get_paramf = galahad_screen_get_paramf;
+ glhd_screen->base.is_format_supported = galahad_screen_is_format_supported;
+ glhd_screen->base.context_create = galahad_screen_context_create;
+ glhd_screen->base.resource_create = galahad_screen_resource_create;
+ glhd_screen->base.resource_from_handle = galahad_screen_resource_from_handle;
+ glhd_screen->base.resource_get_handle = galahad_screen_resource_get_handle;
+ glhd_screen->base.resource_destroy = galahad_screen_resource_destroy;
+ glhd_screen->base.get_tex_surface = galahad_screen_get_tex_surface;
+ glhd_screen->base.tex_surface_destroy = galahad_screen_tex_surface_destroy;
+ glhd_screen->base.user_buffer_create = galahad_screen_user_buffer_create;
+ glhd_screen->base.flush_frontbuffer = galahad_screen_flush_frontbuffer;
+ glhd_screen->base.fence_reference = galahad_screen_fence_reference;
+ glhd_screen->base.fence_signalled = galahad_screen_fence_signalled;
+ glhd_screen->base.fence_finish = galahad_screen_fence_finish;
+
+ glhd_screen->screen = screen;
+
+ return &glhd_screen->base;
+}
diff --git a/src/gallium/drivers/galahad/glhd_screen.h b/src/gallium/drivers/galahad/glhd_screen.h
new file mode 100644
index 0000000000..7862f4af2b
--- /dev/null
+++ b/src/gallium/drivers/galahad/glhd_screen.h
@@ -0,0 +1,48 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef GLHD_SCREEN_H
+#define GLHD_SCREEN_H
+
+#include "pipe/p_screen.h"
+#include "pipe/p_defines.h"
+
+
+struct galahad_screen {
+ struct pipe_screen base;
+
+ struct pipe_screen *screen;
+};
+
+
+static INLINE struct galahad_screen *
+galahad_screen(struct pipe_screen *screen)
+{
+ return (struct galahad_screen *)screen;
+}
+
+#endif /* GLHD_SCREEN_H */
diff --git a/src/gallium/drivers/i915/SConscript b/src/gallium/drivers/i915/SConscript
index 7b69681096..d6e7a8dbd3 100644
--- a/src/gallium/drivers/i915/SConscript
+++ b/src/gallium/drivers/i915/SConscript
@@ -2,6 +2,10 @@ Import('*')
env = env.Clone()
+if msvc:
+ print 'warning: not building i915g'
+ Return()
+
i915 = env.ConvenienceLibrary(
target = 'i915',
source = [
diff --git a/src/gallium/drivers/i915/i915_blit.c b/src/gallium/drivers/i915/i915_blit.c
index c5b5979bf9..0a1b3e0d66 100644
--- a/src/gallium/drivers/i915/i915_blit.c
+++ b/src/gallium/drivers/i915/i915_blit.c
@@ -31,7 +31,6 @@
#include "i915_batch.h"
#include "i915_debug.h"
-#define FILE_DEBUG_FLAG DEBUG_BLIT
void
i915_fill_blit(struct i915_context *i915,
@@ -47,10 +46,8 @@ i915_fill_blit(struct i915_context *i915,
unsigned BR13, CMD;
- I915_DBG(i915,
- "%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
- __FUNCTION__,
- dst_buffer, dst_pitch, dst_offset, x, y, w, h);
+ I915_DBG(DBG_BLIT, "%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
+ __FUNCTION__, dst_buffer, dst_pitch, dst_offset, x, y, w, h);
switch (cpp) {
case 1:
@@ -100,11 +97,11 @@ i915_copy_blit(struct i915_context *i915,
int dst_x2 = dst_x + w;
- I915_DBG(i915,
- "%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,
- dst_buffer, dst_pitch, dst_offset, dst_x, dst_y, w, h);
+ I915_DBG(DBG_BLIT,
+ "%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,
+ dst_buffer, dst_pitch, dst_offset, dst_x, dst_y, w, h);
switch (cpp) {
case 1:
diff --git a/src/gallium/drivers/i915/i915_context.h b/src/gallium/drivers/i915/i915_context.h
index acc0ffe037..ac02ab2332 100644
--- a/src/gallium/drivers/i915/i915_context.h
+++ b/src/gallium/drivers/i915/i915_context.h
@@ -237,8 +237,6 @@ struct i915_context
struct i915_state current;
unsigned hardware_dirty;
-
- unsigned debug;
};
/* A flag for each state_tracker state object:
diff --git a/src/gallium/drivers/i915/i915_debug.c b/src/gallium/drivers/i915/i915_debug.c
index 663fac3055..57d3390dea 100644
--- a/src/gallium/drivers/i915/i915_debug.c
+++ b/src/gallium/drivers/i915/i915_debug.c
@@ -27,11 +27,37 @@
#include "i915_reg.h"
#include "i915_context.h"
+#include "i915_screen.h"
#include "i915_debug.h"
+#include "i915_debug_private.h"
#include "i915_batch.h"
#include "util/u_debug.h"
+
+static const struct debug_named_value debug_options[] = {
+ {"blit", DBG_BLIT, "Print when using the 2d blitter"},
+ {"emit", DBG_EMIT, "State emit information"},
+ {"atoms", DBG_ATOMS, "Print dirty state atoms"},
+ {"flush", DBG_FLUSH, "Flushing information"},
+ {"texture", DBG_TEXTURE, "Texture information"},
+ {"constants", DBG_CONSTANTS, "Constant buffers"},
+ DEBUG_NAMED_VALUE_END
+};
+
+unsigned i915_debug = 0;
+
+void i915_debug_init(struct i915_screen *screen)
+{
+ i915_debug = debug_get_flags_option("I915_DEBUG", debug_options, 0);
+}
+
+
+
+/***********************************************************************
+ * Batchbuffer dumping
+ */
+
static void
PRINTF(
struct debug_stream *stream,
@@ -896,3 +922,66 @@ i915_dump_batchbuffer( struct i915_winsys_batchbuffer *batch )
}
+
+/***********************************************************************
+ * Dirty state atom dumping
+ */
+
+void
+i915_dump_dirty(struct i915_context *i915, const char *func)
+{
+ struct {
+ unsigned dirty;
+ const char *name;
+ } l[] = {
+ {I915_NEW_VIEWPORT, "viewport"},
+ {I915_NEW_RASTERIZER, "rasterizer"},
+ {I915_NEW_FS, "fs"},
+ {I915_NEW_BLEND, "blend"},
+ {I915_NEW_CLIP, "clip"},
+ {I915_NEW_SCISSOR, "scissor"},
+ {I915_NEW_STIPPLE, "stipple"},
+ {I915_NEW_FRAMEBUFFER, "framebuffer"},
+ {I915_NEW_ALPHA_TEST, "alpha_test"},
+ {I915_NEW_DEPTH_STENCIL, "depth_stencil"},
+ {I915_NEW_SAMPLER, "sampler"},
+ {I915_NEW_SAMPLER_VIEW, "sampler_view"},
+ {I915_NEW_CONSTANTS, "constants"},
+ {I915_NEW_VBO, "vbo"},
+ {I915_NEW_VS, "vs"},
+ {0, NULL},
+ };
+ int i;
+
+ debug_printf("%s: ", func);
+ for (i = 0; l[i].name; i++)
+ if (i915->dirty & l[i].dirty)
+ debug_printf("%s ", l[i].name);
+ debug_printf("\n");
+}
+
+void
+i915_dump_hardware_dirty(struct i915_context *i915, const char *func)
+{
+ struct {
+ unsigned dirty;
+ const char *name;
+ } l[] = {
+ {I915_HW_STATIC, "static"},
+ {I915_HW_DYNAMIC, "dynamic"},
+ {I915_HW_SAMPLER, "sampler"},
+ {I915_HW_MAP, "map"},
+ {I915_HW_PROGRAM, "program"},
+ {I915_HW_CONSTANTS, "constants"},
+ {I915_HW_IMMEDIATE, "immediate"},
+ {I915_HW_INVARIENT, "invarient"},
+ {0, NULL},
+ };
+ int i;
+
+ debug_printf("%s: ", func);
+ for (i = 0; l[i].name; i++)
+ if (i915->hardware_dirty & l[i].dirty)
+ debug_printf("%s ", l[i].name);
+ debug_printf("\n");
+}
diff --git a/src/gallium/drivers/i915/i915_debug.h b/src/gallium/drivers/i915/i915_debug.h
index 67b8d9c2f6..8aa09f9c1f 100644
--- a/src/gallium/drivers/i915/i915_debug.h
+++ b/src/gallium/drivers/i915/i915_debug.h
@@ -26,89 +26,51 @@
**************************************************************************/
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ * Jakob Bornecrantz <wallbraker@gmail.com>
*/
#ifndef I915_DEBUG_H
#define I915_DEBUG_H
-#include <stdarg.h>
+#include "util/u_debug.h"
+struct i915_screen;
struct i915_context;
+struct i915_winsys_batchbuffer;
-struct debug_stream
-{
- unsigned offset; /* current gtt offset */
- char *ptr; /* pointer to gtt offset zero */
- char *end; /* pointer to gtt offset zero */
- unsigned print_addresses;
-};
-
-
-/* Internal functions
- */
-void i915_disassemble_program(struct debug_stream *stream,
- const unsigned *program, unsigned sz);
-
-void i915_print_ureg(const char *msg, unsigned ureg);
-
-
-#define DEBUG_BATCH 0x1
-#define DEBUG_BLIT 0x2
-#define DEBUG_BUFFER 0x4
-#define DEBUG_CONSTANTS 0x8
-#define DEBUG_CONTEXT 0x10
-#define DEBUG_DRAW 0x20
-#define DEBUG_DYNAMIC 0x40
-#define DEBUG_FLUSH 0x80
-#define DEBUG_MAP 0x100
-#define DEBUG_PROGRAM 0x200
-#define DEBUG_REGIONS 0x400
-#define DEBUG_SAMPLER 0x800
-#define DEBUG_STATIC 0x1000
-#define DEBUG_SURFACE 0x2000
-#define DEBUG_WINSYS 0x4000
-
-#include "pipe/p_compiler.h"
+#define DBG_BLIT 0x1
+#define DBG_EMIT 0x2
+#define DBG_ATOMS 0x4
+#define DBG_FLUSH 0x8
+#define DBG_TEXTURE 0x10
+#define DBG_CONSTANTS 0x20
-#if defined(DEBUG) && defined(FILE_DEBUG_FLAG)
+extern unsigned i915_debug;
-#include "util/u_simple_screen.h"
+static INLINE boolean
+I915_DBG_ON(unsigned flags)
+{
+ return i915_debug & flags;
+}
static INLINE void
-I915_DBG(
- struct i915_context *i915,
- const char *fmt,
- ... )
+I915_DBG(unsigned flags, const char *fmt, ...)
{
- if ((i915)->debug & FILE_DEBUG_FLAG) {
+ if (I915_DBG_ON(flags)) {
va_list args;
- va_start( args, fmt );
- debug_vprintf( fmt, args );
- va_end( args );
+ va_start(args, fmt);
+ debug_vprintf(fmt, args);
+ va_end(args);
}
}
-#else
-
-static INLINE void
-I915_DBG(
- struct i915_context *i915,
- const char *fmt,
- ... )
-{
- (void) i915;
- (void) fmt;
-}
-
-#endif
-
-
-struct i915_winsys_batchbuffer;
+void i915_debug_init(struct i915_screen *i915);
-void i915_dump_batchbuffer( struct i915_winsys_batchbuffer *i915 );
+void i915_dump_batchbuffer(struct i915_winsys_batchbuffer *i915);
-void i915_debug_init( struct i915_context *i915 );
+void i915_dump_dirty(struct i915_context *i915, const char *func);
+void i915_dump_hardware_dirty(struct i915_context *i915, const char *func);
#endif
diff --git a/src/gallium/drivers/i915/i915_debug_fp.c b/src/gallium/drivers/i915/i915_debug_fp.c
index f41c51f299..50f49c540f 100644
--- a/src/gallium/drivers/i915/i915_debug_fp.c
+++ b/src/gallium/drivers/i915/i915_debug_fp.c
@@ -28,6 +28,7 @@
#include "i915_reg.h"
#include "i915_debug.h"
+#include "i915_debug_private.h"
#include "util/u_debug.h"
diff --git a/src/gallium/drivers/i915/i915_debug_private.h b/src/gallium/drivers/i915/i915_debug_private.h
new file mode 100644
index 0000000000..b3668d0848
--- /dev/null
+++ b/src/gallium/drivers/i915/i915_debug_private.h
@@ -0,0 +1,45 @@
+/**************************************************************************
+ *
+ * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* Authors: Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef I915_DEBUG_PRIVATE_H
+#define I915_DEBUG_PRIVATE_H
+
+struct debug_stream
+{
+ unsigned offset; /* current gtt offset */
+ char *ptr; /* pointer to gtt offset zero */
+ char *end; /* pointer to gtt offset zero */
+ unsigned print_addresses;
+};
+
+void i915_disassemble_program(struct debug_stream *stream,
+ const unsigned *program, unsigned sz);
+
+#endif
diff --git a/src/gallium/drivers/i915/i915_flush.c b/src/gallium/drivers/i915/i915_flush.c
index 1582168eba..967146479d 100644
--- a/src/gallium/drivers/i915/i915_flush.c
+++ b/src/gallium/drivers/i915/i915_flush.c
@@ -35,6 +35,7 @@
#include "i915_context.h"
#include "i915_reg.h"
#include "i915_batch.h"
+#include "i915_debug.h"
static void i915_flush( struct pipe_context *pipe,
@@ -76,9 +77,9 @@ static void i915_flush( struct pipe_context *pipe,
*/
FLUSH_BATCH(fence);
i915->vbo_flushed = 1;
-}
-
+ I915_DBG(DBG_FLUSH, "%s: #####\n", __FUNCTION__);
+}
void i915_init_flush_functions( struct i915_context *i915 )
{
diff --git a/src/gallium/drivers/i915/i915_prim_vbuf.c b/src/gallium/drivers/i915/i915_prim_vbuf.c
index f8665acbe1..bd046bd905 100644
--- a/src/gallium/drivers/i915/i915_prim_vbuf.c
+++ b/src/gallium/drivers/i915/i915_prim_vbuf.c
@@ -52,8 +52,7 @@
#include "i915_state.h"
-#undef VBUF_USE_FIFO
-#undef VBUF_MAP_BUFFER
+#define VBUF_MAP_BUFFER
/**
* Primitive renderer for i915.
@@ -79,23 +78,18 @@ struct i915_vbuf_render {
struct i915_winsys_buffer *vbo;
size_t vbo_size; /**< current size of allocated buffer */
size_t vbo_alloc_size; /**< minimum buffer size to allocate */
- size_t vbo_offset;
+ size_t vbo_hw_offset; /**< offset that we program the hardware with */
+ size_t vbo_sw_offset; /**< offset that we work with */
+ size_t vbo_index; /**< index offset to be added to all indices */
void *vbo_ptr;
size_t vbo_max_used;
+ size_t vbo_max_index; /**< index offset to be added to all indices */
#ifndef VBUF_MAP_BUFFER
size_t map_used_start;
size_t map_used_end;
size_t map_size;
#endif
-
-#ifdef VBUF_USE_FIFO
- /* Stuff for the pool */
- struct util_fifo *pool_fifo;
- unsigned pool_used;
- unsigned pool_buffer_size;
- boolean pool_not_used;
-#endif
};
@@ -109,6 +103,35 @@ i915_vbuf_render(struct vbuf_render *render)
return (struct i915_vbuf_render *)render;
}
+/**
+ * If vbo state differs between renderer and context
+ * push state to the context. This function pushes
+ * hw_offset to i915->vbo_offset and vbo to i915->vbo.
+ *
+ * Side effects:
+ * May updates context vbo_offset and vbo fields.
+ */
+static void
+i915_vbuf_update_vbo_state(struct vbuf_render *render)
+{
+ struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
+ struct i915_context *i915 = i915_render->i915;
+
+ if (i915->vbo != i915_render->vbo ||
+ i915->vbo_offset != i915_render->vbo_hw_offset) {
+ i915->vbo = i915_render->vbo;
+ i915->vbo_offset = i915_render->vbo_hw_offset;
+ i915->dirty |= I915_NEW_VBO;
+ }
+}
+
+/**
+ * Callback exported to the draw module.
+ * Returns the current vertex_info.
+ *
+ * Side effects:
+ * If state is dirty update derived state.
+ */
static const struct vertex_info *
i915_vbuf_render_get_vertex_info(struct vbuf_render *render)
{
@@ -123,12 +146,18 @@ i915_vbuf_render_get_vertex_info(struct vbuf_render *render)
return &i915->current.vertex_info;
}
+/**
+ * Reserve space in the vbo for vertices.
+ *
+ * Side effects:
+ * None.
+ */
static boolean
i915_vbuf_render_reserve(struct i915_vbuf_render *i915_render, size_t size)
{
struct i915_context *i915 = i915_render->i915;
- if (i915_render->vbo_size < size + i915_render->vbo_offset)
+ if (i915_render->vbo_size < size + i915_render->vbo_sw_offset)
return FALSE;
if (i915->vbo_flushed)
@@ -137,28 +166,28 @@ i915_vbuf_render_reserve(struct i915_vbuf_render *i915_render, size_t size)
return TRUE;
}
+/**
+ * Allocate a new vbo buffer should there not be enough space for
+ * the requested number of vertices by the draw module.
+ *
+ * Side effects:
+ * Updates hw_offset, sw_offset, index and allocates a new buffer.
+ */
static void
i915_vbuf_render_new_buf(struct i915_vbuf_render *i915_render, size_t size)
{
struct i915_context *i915 = i915_render->i915;
struct i915_winsys *iws = i915->iws;
- if (i915_render->vbo) {
-#ifdef VBUF_USE_FIFO
- if (i915_render->pool_not_used)
- iws->buffer_destroy(iws, i915_render->vbo);
- else
- u_fifo_add(i915_render->pool_fifo, i915_render->vbo);
- i915_render->vbo = NULL;
-#else
+ if (i915_render->vbo)
iws->buffer_destroy(iws, i915_render->vbo);
-#endif
- }
i915->vbo_flushed = 0;
i915_render->vbo_size = MAX2(size, i915_render->vbo_alloc_size);
- i915_render->vbo_offset = 0;
+ i915_render->vbo_hw_offset = 0;
+ i915_render->vbo_sw_offset = 0;
+ i915_render->vbo_index = 0;
#ifndef VBUF_MAP_BUFFER
if (i915_render->vbo_size > i915_render->map_size) {
@@ -168,52 +197,51 @@ i915_vbuf_render_new_buf(struct i915_vbuf_render *i915_render, size_t size)
}
#endif
-#ifdef VBUF_USE_FIFO
- if (i915_render->vbo_size != i915_render->pool_buffer_size) {
- i915_render->pool_not_used = TRUE;
- i915_render->vbo = iws->buffer_create(iws, i915_render->vbo_size, 64,
- I915_NEW_VERTEX);
- } else {
- i915_render->pool_not_used = FALSE;
-
- if (i915_render->pool_used >= 2) {
- FLUSH_BATCH(NULL);
- i915->vbo_flushed = 0;
- i915_render->pool_used = 0;
- }
- u_fifo_pop(i915_render->pool_fifo, (void**)&i915_render->vbo);
- }
-#else
i915_render->vbo = iws->buffer_create(iws, i915_render->vbo_size,
64, I915_NEW_VERTEX);
-#endif
}
+/**
+ * Callback exported to the draw module.
+ *
+ * Side effects:
+ * Updates hw_offset, sw_offset, index and may allocate
+ * a new buffer. Also updates may update the vbo state
+ * on the i915 context.
+ */
static boolean
i915_vbuf_render_allocate_vertices(struct vbuf_render *render,
ushort vertex_size,
ushort nr_vertices)
{
struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
- struct i915_context *i915 = i915_render->i915;
size_t size = (size_t)vertex_size * (size_t)nr_vertices;
+ size_t offset;
- /* FIXME: handle failure */
- assert(!i915->vbo);
+ /*
+ * Align sw_offset with first multiple of vertex size from hw_offset.
+ * Set index to be the multiples from from hw_offset to sw_offset.
+ * i915_vbuf_render_new_buf will reset index, sw_offset, hw_offset
+ * when it allocates a new buffer this is correct.
+ */
+ {
+ offset = i915_render->vbo_sw_offset - i915_render->vbo_hw_offset;
+ offset = util_align_npot(offset, vertex_size);
+ i915_render->vbo_sw_offset = i915_render->vbo_hw_offset + offset;
+ i915_render->vbo_index = offset / vertex_size;
+ }
- if (!i915_vbuf_render_reserve(i915_render, size)) {
-#ifdef VBUF_USE_FIFO
- /* incase we flushed reset the number of pool buffers used */
- if (i915->vbo_flushed)
- i915_render->pool_used = 0;
-#endif
+ if (!i915_vbuf_render_reserve(i915_render, size))
i915_vbuf_render_new_buf(i915_render, size);
- }
+
+ /*
+ * If a new buffer has been alocated sw_offset,
+ * hw_offset & index will be reset by new_buf
+ */
i915_render->vertex_size = vertex_size;
- i915->vbo = i915_render->vbo;
- i915->vbo_offset = i915_render->vbo_offset;
- i915->dirty |= I915_NEW_VBO;
+
+ i915_vbuf_update_vbo_state(render);
if (!i915_render->vbo)
return FALSE;
@@ -232,7 +260,7 @@ i915_vbuf_render_map_vertices(struct vbuf_render *render)
#ifdef VBUF_MAP_BUFFER
i915_render->vbo_ptr = iws->buffer_map(iws, i915_render->vbo, TRUE);
- return (unsigned char *)i915_render->vbo_ptr + i915_render->vbo_offset;
+ return (unsigned char *)i915_render->vbo_ptr + i915_render->vbo_sw_offset;
#else
(void)iws;
return (unsigned char *)i915_render->vbo_ptr;
@@ -248,6 +276,7 @@ i915_vbuf_render_unmap_vertices(struct vbuf_render *render,
struct i915_context *i915 = i915_render->i915;
struct i915_winsys *iws = i915->iws;
+ i915_render->vbo_max_index = max_index;
i915_render->vbo_max_used = MAX2(i915_render->vbo_max_used, i915_render->vertex_size * (max_index + 1));
#ifdef VBUF_MAP_BUFFER
iws->buffer_unmap(iws, i915_render->vbo);
@@ -255,13 +284,36 @@ i915_vbuf_render_unmap_vertices(struct vbuf_render *render,
i915_render->map_used_start = i915_render->vertex_size * min_index;
i915_render->map_used_end = i915_render->vertex_size * (max_index + 1);
iws->buffer_write(iws, i915_render->vbo,
- i915_render->map_used_start + i915_render->vbo_offset,
+ i915_render->map_used_start + i915_render->vbo_sw_offset,
i915_render->map_used_end - i915_render->map_used_start,
(unsigned char *)i915_render->vbo_ptr + i915_render->map_used_start);
#endif
}
+/**
+ * Ensure that the given max_index given is not larger ushort max.
+ * If it is larger then ushort max it advanced the hw_offset to the
+ * same position in the vbo as sw_offset and set index to zero.
+ *
+ * Side effects:
+ * On failure update hw_offset and index.
+ */
+static void
+i915_vbuf_ensure_index_bounds(struct vbuf_render *render,
+ unsigned max_index)
+{
+ struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
+
+ if (max_index + i915_render->vbo_index < ((1 << 17) - 1))
+ return;
+
+ i915_render->vbo_hw_offset = i915_render->vbo_sw_offset;
+ i915_render->vbo_index = 0;
+
+ i915_vbuf_update_vbo_state(render);
+}
+
static boolean
i915_vbuf_render_set_primitive(struct vbuf_render *render,
unsigned prim)
@@ -327,7 +379,9 @@ draw_arrays_generate_indices(struct vbuf_render *render,
struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
struct i915_context *i915 = i915_render->i915;
unsigned i;
- unsigned end = start + nr;
+ unsigned end = start + nr + i915_render->vbo_index;
+ start += i915_render->vbo_index;
+
switch(type) {
case 0:
for (i = start; i+1 < end; i += 2)
@@ -391,16 +445,18 @@ draw_arrays_fallback(struct vbuf_render *render,
struct i915_context *i915 = i915_render->i915;
unsigned nr_indices;
+ nr_indices = draw_arrays_calc_nr_indices(nr, i915_render->fallback);
+ if (!nr_indices)
+ return;
+
+ i915_vbuf_ensure_index_bounds(render, start + nr_indices);
+
if (i915->dirty)
i915_update_derived(i915);
if (i915->hardware_dirty)
i915_emit_hardware_state(i915);
- nr_indices = draw_arrays_calc_nr_indices(nr, i915_render->fallback);
- if (!nr_indices)
- return;
-
if (!BEGIN_BATCH(1 + (nr_indices + 1)/2, 1)) {
FLUSH_BATCH(NULL);
@@ -415,6 +471,7 @@ draw_arrays_fallback(struct vbuf_render *render,
goto out;
}
}
+
OUT_BATCH(_3DPRIMITIVE |
PRIM_INDIRECT |
i915_render->hwprim |
@@ -440,6 +497,9 @@ i915_vbuf_render_draw_arrays(struct vbuf_render *render,
return;
}
+ i915_vbuf_ensure_index_bounds(render, start + nr);
+ start += i915_render->vbo_index;
+
if (i915->dirty)
i915_update_derived(i915);
@@ -485,35 +545,36 @@ draw_generate_indices(struct vbuf_render *render,
struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
struct i915_context *i915 = i915_render->i915;
unsigned i;
+ unsigned o = i915_render->vbo_index;
switch(type) {
case 0:
for (i = 0; i + 1 < nr_indices; i += 2) {
- OUT_BATCH(indices[i] | indices[i+1] << 16);
+ OUT_BATCH((o+indices[i]) | (o+indices[i+1]) << 16);
}
if (i < nr_indices) {
- OUT_BATCH(indices[i]);
+ OUT_BATCH((o+indices[i]));
}
break;
case PIPE_PRIM_LINE_LOOP:
if (nr_indices >= 2) {
for (i = 1; i < nr_indices; i++)
- OUT_BATCH(indices[i-1] | indices[i] << 16);
- OUT_BATCH(indices[i-1] | indices[0] << 16);
+ OUT_BATCH((o+indices[i-1]) | (o+indices[i]) << 16);
+ OUT_BATCH((o+indices[i-1]) | (o+indices[0]) << 16);
}
break;
case PIPE_PRIM_QUADS:
for (i = 0; i + 3 < nr_indices; i += 4) {
- OUT_BATCH(indices[i+0] | indices[i+1] << 16);
- OUT_BATCH(indices[i+3] | indices[i+1] << 16);
- OUT_BATCH(indices[i+2] | indices[i+3] << 16);
+ OUT_BATCH((o+indices[i+0]) | (o+indices[i+1]) << 16);
+ OUT_BATCH((o+indices[i+3]) | (o+indices[i+1]) << 16);
+ OUT_BATCH((o+indices[i+2]) | (o+indices[i+3]) << 16);
}
break;
case PIPE_PRIM_QUAD_STRIP:
for (i = 0; i + 3 < nr_indices; i += 2) {
- OUT_BATCH(indices[i+0] | indices[i+1] << 16);
- OUT_BATCH(indices[i+3] | indices[i+2] << 16);
- OUT_BATCH(indices[i+0] | indices[i+3] << 16);
+ OUT_BATCH((o+indices[i+0]) | (o+indices[i+1]) << 16);
+ OUT_BATCH((o+indices[i+3]) | (o+indices[i+2]) << 16);
+ OUT_BATCH((o+indices[i+0]) | (o+indices[i+3]) << 16);
}
break;
default:
@@ -558,6 +619,8 @@ i915_vbuf_render_draw_elements(struct vbuf_render *render,
if (!nr_indices)
return;
+ i915_vbuf_ensure_index_bounds(render, i915_render->vbo_max_index);
+
if (i915->dirty)
i915_update_derived(i915);
@@ -597,14 +660,15 @@ static void
i915_vbuf_render_release_vertices(struct vbuf_render *render)
{
struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
- struct i915_context *i915 = i915_render->i915;
-
- assert(i915->vbo);
- i915_render->vbo_offset += i915_render->vbo_max_used;
+ i915_render->vbo_sw_offset += i915_render->vbo_max_used;
i915_render->vbo_max_used = 0;
- i915->vbo = NULL;
- i915->dirty |= I915_NEW_VBO;
+
+ /*
+ * Micro optimization, by calling update here we the offset change
+ * will be picked up on the next pipe_context::draw_*.
+ */
+ i915_vbuf_update_vbo_state(render);
}
static void
@@ -652,7 +716,8 @@ i915_vbuf_render_create(struct i915_context *i915)
i915_render->vbo = NULL;
i915_render->vbo_ptr = NULL;
i915_render->vbo_size = 0;
- i915_render->vbo_offset = 0;
+ i915_render->vbo_hw_offset = 0;
+ i915_render->vbo_sw_offset = 0;
i915_render->vbo_alloc_size = i915_render->base.max_vertex_buffer_bytes * 4;
#ifdef VBUF_USE_POOL
diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c
index bb0b85d74c..77345d5f71 100644
--- a/src/gallium/drivers/i915/i915_screen.c
+++ b/src/gallium/drivers/i915/i915_screen.c
@@ -31,6 +31,7 @@
#include "util/u_string.h"
#include "i915_reg.h"
+#include "i915_debug.h"
#include "i915_context.h"
#include "i915_screen.h"
#include "i915_surface.h"
@@ -331,5 +332,7 @@ i915_screen_create(struct i915_winsys *iws)
i915_init_screen_resource_functions(is);
i915_init_screen_surface_functions(is);
+ i915_debug_init(is);
+
return &is->base;
}
diff --git a/src/gallium/drivers/i915/i915_state.h b/src/gallium/drivers/i915/i915_state.h
index 86c6b0027d..7795046f06 100644
--- a/src/gallium/drivers/i915/i915_state.h
+++ b/src/gallium/drivers/i915/i915_state.h
@@ -35,16 +35,21 @@ struct i915_context;
struct i915_tracked_state {
+ const char *name;
+ void (*update)(struct i915_context *);
unsigned dirty;
- void (*update)( struct i915_context * );
};
-void i915_update_immediate( struct i915_context *i915 );
-void i915_update_dynamic( struct i915_context *i915 );
-void i915_update_derived( struct i915_context *i915 );
-void i915_update_samplers( struct i915_context *i915 );
-void i915_update_textures(struct i915_context *i915);
+extern struct i915_tracked_state i915_update_vertex_layout;
-void i915_emit_hardware_state( struct i915_context *i915 );
+extern struct i915_tracked_state i915_hw_samplers;
+extern struct i915_tracked_state i915_hw_sampler_views;
+extern struct i915_tracked_state i915_hw_immediate;
+extern struct i915_tracked_state i915_hw_dynamic;
+extern struct i915_tracked_state i915_hw_fs;
+extern struct i915_tracked_state i915_hw_framebuffer;
+
+void i915_update_derived(struct i915_context *i915);
+void i915_emit_hardware_state(struct i915_context *i915);
#endif
diff --git a/src/gallium/drivers/i915/i915_state_derived.c b/src/gallium/drivers/i915/i915_state_derived.c
index 4da46772b5..c059540357 100644
--- a/src/gallium/drivers/i915/i915_state_derived.c
+++ b/src/gallium/drivers/i915/i915_state_derived.c
@@ -32,15 +32,16 @@
#include "draw/draw_vertex.h"
#include "i915_context.h"
#include "i915_state.h"
+#include "i915_debug.h"
#include "i915_reg.h"
-/**
+/***********************************************************************
* Determine the hardware vertex layout.
* Depends on vertex/fragment shader state.
*/
-static void calculate_vertex_layout( struct i915_context *i915 )
+static void calculate_vertex_layout(struct i915_context *i915)
{
const struct i915_fragment_shader *fs = i915->fs;
const enum interp_mode colorInterp = i915->rasterizer->color_interp;
@@ -146,37 +147,71 @@ static void calculate_vertex_layout( struct i915_context *i915 )
}
}
+struct i915_tracked_state i915_update_vertex_layout = {
+ "vertex_layout",
+ calculate_vertex_layout,
+ I915_NEW_RASTERIZER | I915_NEW_FS | I915_NEW_VS
+};
-/* Hopefully this will remain quite simple, otherwise need to pull in
- * something like the state tracker mechanism.
+/***********************************************************************
+ * Update fragment state
*/
-void i915_update_derived( struct i915_context *i915 )
+static void update_fs(struct i915_context *i915)
{
- if (i915->dirty & (I915_NEW_RASTERIZER | I915_NEW_FS | I915_NEW_VS))
- calculate_vertex_layout( i915 );
-
- if (i915->dirty & (I915_NEW_SAMPLER | I915_NEW_SAMPLER_VIEW))
- i915_update_samplers(i915);
-
- if (i915->dirty & I915_NEW_SAMPLER_VIEW)
- i915_update_textures(i915);
+ i915->hardware_dirty |= I915_HW_PROGRAM; /* XXX right? */
+}
- if (i915->dirty)
- i915_update_immediate( i915 );
+struct i915_tracked_state i915_hw_fs = {
+ "fs",
+ update_fs,
+ I915_NEW_FS
+};
- if (i915->dirty)
- i915_update_dynamic( i915 );
- if (i915->dirty & I915_NEW_FS) {
- i915->hardware_dirty |= I915_HW_PROGRAM; /* XXX right? */
- }
+/***********************************************************************
+ * Update framebuffer state
+ */
+static void update_framebuffer(struct i915_context *i915)
+{
/* HW emit currently references framebuffer state directly:
*/
- if (i915->dirty & I915_NEW_FRAMEBUFFER)
- i915->hardware_dirty |= I915_HW_STATIC;
+ i915->hardware_dirty |= I915_HW_STATIC;
+}
+
+struct i915_tracked_state i915_hw_framebuffer = {
+ "framebuffer",
+ update_framebuffer,
+ I915_NEW_FRAMEBUFFER
+};
+
+
+
+/***********************************************************************
+ */
+static struct i915_tracked_state *atoms[] = {
+ &i915_update_vertex_layout,
+ &i915_hw_samplers,
+ &i915_hw_sampler_views,
+ &i915_hw_immediate,
+ &i915_hw_dynamic,
+ &i915_hw_fs,
+ &i915_hw_framebuffer,
+ NULL,
+};
+
+void i915_update_derived(struct i915_context *i915)
+{
+ int i;
+
+ if (I915_DBG_ON(DBG_ATOMS))
+ i915_dump_dirty(i915, __FUNCTION__);
+
+ for (i = 0; atoms[i]; i++)
+ if (atoms[i]->dirty & i915->dirty)
+ atoms[i]->update(i915);
i915->dirty = 0;
}
diff --git a/src/gallium/drivers/i915/i915_state_dynamic.c b/src/gallium/drivers/i915/i915_state_dynamic.c
index 9c6723b391..d964483ac7 100644
--- a/src/gallium/drivers/i915/i915_state_dynamic.c
+++ b/src/gallium/drivers/i915/i915_state_dynamic.c
@@ -1,8 +1,8 @@
/**************************************************************************
- *
+ *
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
@@ -10,11 +10,11 @@
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
- *
+ *
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
@@ -22,7 +22,7 @@
* 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 "i915_batch.h"
@@ -34,10 +34,9 @@
#include "util/u_memory.h"
#include "util/u_pack_color.h"
-#define FILE_DEBUG_FLAG DEBUG_STATE
/* State that we have chosen to store in the DYNAMIC segment of the
- * i915 indirect state mechanism.
+ * i915 indirect state mechanism.
*
* Can't cache these in the way we do the static state, as there is no
* start/size in the command packet, instead an 'end' value that gets
@@ -47,10 +46,10 @@
* (active) state every time a 4kb boundary is crossed.
*/
-static INLINE void set_dynamic_indirect( struct i915_context *i915,
- unsigned offset,
- const unsigned *src,
- unsigned dwords )
+static INLINE void set_dynamic_indirect(struct i915_context *i915,
+ unsigned offset,
+ const unsigned *src,
+ unsigned dwords)
{
unsigned i;
@@ -61,38 +60,41 @@ static INLINE void set_dynamic_indirect( struct i915_context *i915,
}
+
/***********************************************************************
- * Modes4: stencil masks and logicop
+ * Modes4: stencil masks and logicop
*/
-static void upload_MODES4( struct i915_context *i915 )
+static void upload_MODES4(struct i915_context *i915)
{
unsigned modes4 = 0;
- /* I915_NEW_STENCIL */
+ /* I915_NEW_STENCIL
+ */
modes4 |= i915->depth_stencil->stencil_modes4;
- /* I915_NEW_BLEND */
+
+ /* I915_NEW_BLEND
+ */
modes4 |= i915->blend->modes4;
- /* Always, so that we know when state is in-active:
+ /* Always, so that we know when state is in-active:
*/
- set_dynamic_indirect( i915,
- I915_DYNAMIC_MODES4,
- &modes4,
- 1 );
+ set_dynamic_indirect(i915,
+ I915_DYNAMIC_MODES4,
+ &modes4,
+ 1);
}
const struct i915_tracked_state i915_upload_MODES4 = {
- I915_NEW_BLEND | I915_NEW_DEPTH_STENCIL,
- upload_MODES4
+ "MODES4",
+ upload_MODES4,
+ I915_NEW_BLEND | I915_NEW_DEPTH_STENCIL
};
-
/***********************************************************************
*/
-
-static void upload_BFO( struct i915_context *i915 )
+static void upload_BFO(struct i915_context *i915)
{
unsigned bfo[2];
bfo[0] = i915->depth_stencil->bfo[0];
@@ -101,88 +103,89 @@ static void upload_BFO( struct i915_context *i915 )
if (bfo[0] & BFO_ENABLE_STENCIL_REF) {
bfo[0] |= i915->stencil_ref.ref_value[1] << BFO_STENCIL_REF_SHIFT;
}
- set_dynamic_indirect( i915,
- I915_DYNAMIC_BFO_0,
- &(bfo[0]),
- 2 );
+
+ set_dynamic_indirect(i915,
+ I915_DYNAMIC_BFO_0,
+ &(bfo[0]),
+ 2);
}
const struct i915_tracked_state i915_upload_BFO = {
- I915_NEW_DEPTH_STENCIL,
- upload_BFO
+ "BFO",
+ upload_BFO,
+ I915_NEW_DEPTH_STENCIL
};
+
/***********************************************************************
*/
-
-
-static void upload_BLENDCOLOR( struct i915_context *i915 )
+static void upload_BLENDCOLOR(struct i915_context *i915)
{
unsigned bc[2];
- memset( bc, 0, sizeof(bc) );
+ memset(bc, 0, sizeof(bc));
- /* I915_NEW_BLEND {_COLOR}
+ /* I915_NEW_BLEND
*/
{
const float *color = i915->blend_color.color;
bc[0] = _3DSTATE_CONST_BLEND_COLOR_CMD;
- bc[1] = pack_ui32_float4( color[0],
- color[1],
- color[2],
- color[3] );
+ bc[1] = pack_ui32_float4(color[0],
+ color[1],
+ color[2],
+ color[3]);
}
- set_dynamic_indirect( i915,
- I915_DYNAMIC_BC_0,
- bc,
- 2 );
+ set_dynamic_indirect(i915,
+ I915_DYNAMIC_BC_0,
+ bc,
+ 2);
}
const struct i915_tracked_state i915_upload_BLENDCOLOR = {
- I915_NEW_BLEND,
- upload_BLENDCOLOR
+ "BLENDCOLOR",
+ upload_BLENDCOLOR,
+ I915_NEW_BLEND
};
-/***********************************************************************
- */
-static void upload_IAB( struct i915_context *i915 )
+/***********************************************************************
+ */
+static void upload_IAB(struct i915_context *i915)
{
unsigned iab = i915->blend->iab;
-
- set_dynamic_indirect( i915,
- I915_DYNAMIC_IAB,
- &iab,
- 1 );
+ set_dynamic_indirect(i915,
+ I915_DYNAMIC_IAB,
+ &iab,
+ 1);
}
const struct i915_tracked_state i915_upload_IAB = {
- I915_NEW_BLEND,
- upload_IAB
+ "IAB",
+ upload_IAB,
+ I915_NEW_BLEND
};
+
/***********************************************************************
*/
-
-
-
-static void upload_DEPTHSCALE( struct i915_context *i915 )
+static void upload_DEPTHSCALE(struct i915_context *i915)
{
- set_dynamic_indirect( i915,
- I915_DYNAMIC_DEPTHSCALE_0,
- &(i915->rasterizer->ds[0].u),
- 2 );
+ set_dynamic_indirect(i915,
+ I915_DYNAMIC_DEPTHSCALE_0,
+ &(i915->rasterizer->ds[0].u),
+ 2);
}
const struct i915_tracked_state i915_upload_DEPTHSCALE = {
- I915_NEW_RASTERIZER,
- upload_DEPTHSCALE
+ "DEPTHSCALE",
+ upload_DEPTHSCALE,
+ I915_NEW_RASTERIZER
};
@@ -196,10 +199,9 @@ const struct i915_tracked_state i915_upload_DEPTHSCALE = {
* XXX: does stipple pattern need to be adjusted according to
* the window position?
*
- * XXX: possibly need workaround for conform paths test.
+ * XXX: possibly need workaround for conform paths test.
*/
-
-static void upload_STIPPLE( struct i915_context *i915 )
+static void upload_STIPPLE(struct i915_context *i915)
{
unsigned st[2];
@@ -210,7 +212,6 @@ static void upload_STIPPLE( struct i915_context *i915 )
*/
st[1] |= i915->rasterizer->st;
-
/* I915_NEW_STIPPLE
*/
{
@@ -225,73 +226,75 @@ static void upload_STIPPLE( struct i915_context *i915 )
/* Not sure what to do about fallbacks, so for now just dont:
*/
st[1] |= ((p[0] << 0) |
- (p[1] << 4) |
- (p[2] << 8) |
- (p[3] << 12));
+ (p[1] << 4) |
+ (p[2] << 8) |
+ (p[3] << 12));
}
-
- set_dynamic_indirect( i915,
- I915_DYNAMIC_STP_0,
- &st[0],
- 2 );
+ set_dynamic_indirect(i915,
+ I915_DYNAMIC_STP_0,
+ &st[0],
+ 2);
}
-
const struct i915_tracked_state i915_upload_STIPPLE = {
- I915_NEW_RASTERIZER | I915_NEW_STIPPLE,
- upload_STIPPLE
+ "STIPPLE",
+ upload_STIPPLE,
+ I915_NEW_RASTERIZER | I915_NEW_STIPPLE
};
/***********************************************************************
- * Scissor.
+ * Scissor enable
*/
static void upload_SCISSOR_ENABLE( struct i915_context *i915 )
{
- set_dynamic_indirect( i915,
- I915_DYNAMIC_SC_ENA_0,
- &(i915->rasterizer->sc[0]),
- 1 );
+ set_dynamic_indirect(i915,
+ I915_DYNAMIC_SC_ENA_0,
+ &(i915->rasterizer->sc[0]),
+ 1);
}
const struct i915_tracked_state i915_upload_SCISSOR_ENABLE = {
- I915_NEW_RASTERIZER,
- upload_SCISSOR_ENABLE
+ "SCISSOR ENABLE",
+ upload_SCISSOR_ENABLE,
+ I915_NEW_RASTERIZER
};
-static void upload_SCISSOR_RECT( struct i915_context *i915 )
+/***********************************************************************
+ * Scissor rect
+ */
+static void upload_SCISSOR_RECT(struct i915_context *i915)
{
unsigned x1 = i915->scissor.minx;
unsigned y1 = i915->scissor.miny;
unsigned x2 = i915->scissor.maxx;
unsigned y2 = i915->scissor.maxy;
unsigned sc[3];
-
+
sc[0] = _3DSTATE_SCISSOR_RECT_0_CMD;
sc[1] = (y1 << 16) | (x1 & 0xffff);
sc[2] = (y2 << 16) | (x2 & 0xffff);
- set_dynamic_indirect( i915,
- I915_DYNAMIC_SC_RECT_0,
- &sc[0],
- 3 );
+ set_dynamic_indirect(i915,
+ I915_DYNAMIC_SC_RECT_0,
+ &sc[0],
+ 3);
}
-
const struct i915_tracked_state i915_upload_SCISSOR_RECT = {
- I915_NEW_SCISSOR,
- upload_SCISSOR_RECT
+ "SCISSOR RECT",
+ upload_SCISSOR_RECT,
+ I915_NEW_SCISSOR
};
-
-
-
+/***********************************************************************
+ */
static const struct i915_tracked_state *atoms[] = {
&i915_upload_MODES4,
&i915_upload_BFO,
@@ -306,12 +309,17 @@ static const struct i915_tracked_state *atoms[] = {
/* These will be dynamic indirect state commands, but for now just end
* up on the batch buffer with everything else.
*/
-void i915_update_dynamic( struct i915_context *i915 )
+static void update_dynamic(struct i915_context *i915)
{
int i;
for (i = 0; i < Elements(atoms); i++)
if (i915->dirty & atoms[i]->dirty)
- atoms[i]->update( i915 );
+ atoms[i]->update(i915);
}
+struct i915_tracked_state i915_hw_dynamic = {
+ "dynamic",
+ update_dynamic,
+ ~0 /* all state atoms, becuase we do internal checking */
+};
diff --git a/src/gallium/drivers/i915/i915_state_emit.c b/src/gallium/drivers/i915/i915_state_emit.c
index 22082fece8..bbf9ff51f5 100644
--- a/src/gallium/drivers/i915/i915_state_emit.c
+++ b/src/gallium/drivers/i915/i915_state_emit.c
@@ -29,6 +29,7 @@
#include "i915_reg.h"
#include "i915_context.h"
#include "i915_batch.h"
+#include "i915_debug.h"
#include "i915_reg.h"
#include "i915_resource.h"
@@ -111,15 +112,20 @@ i915_emit_hardware_state(struct i915_context *i915 )
3
) * 3/2; /* plus 50% margin */
-#if 0
- debug_printf("i915_emit_hardware_state: %d dwords, %d relocs\n", dwords, relocs);
-#endif
-
+ uintptr_t save_ptr;
+ size_t save_relocs;
+
+ if (I915_DBG_ON(DBG_ATOMS))
+ i915_dump_hardware_dirty(i915, __FUNCTION__);
+
if(!BEGIN_BATCH(dwords, relocs)) {
FLUSH_BATCH(NULL);
assert(BEGIN_BATCH(dwords, relocs));
}
+ save_ptr = (uintptr_t)i915->batch->ptr;
+ save_relocs = i915->batch->relocs;
+
/* 14 dwords, 0 relocs */
if (i915->hardware_dirty & I915_HW_INVARIENT)
{
@@ -399,6 +405,9 @@ i915_emit_hardware_state(struct i915_context *i915 )
OUT_BATCH(0);
}
+ I915_DBG(DBG_EMIT, "%s: used %d dwords, %d relocs\n", __FUNCTION__,
+ ((uintptr_t)i915->batch->ptr - save_ptr) / 4,
+ i915->batch->relocs - save_relocs);
i915->hardware_dirty = 0;
}
diff --git a/src/gallium/drivers/i915/i915_state_immediate.c b/src/gallium/drivers/i915/i915_state_immediate.c
index 8cec699285..f9ade7077f 100644
--- a/src/gallium/drivers/i915/i915_state_immediate.c
+++ b/src/gallium/drivers/i915/i915_state_immediate.c
@@ -1,8 +1,8 @@
/**************************************************************************
- *
+ *
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
@@ -10,11 +10,11 @@
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
- *
+ *
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
@@ -22,13 +22,13 @@
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
+ *
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
-
+
#include "i915_state_inlines.h"
#include "i915_context.h"
#include "i915_state.h"
@@ -46,30 +46,31 @@
/***********************************************************************
- * S0,S1: Vertex buffer state.
+ * S0,S1: Vertex buffer state.
*/
static void upload_S0S1(struct i915_context *i915)
{
unsigned LIS0, LIS1;
- /* I915_NEW_VBO */
- /* TODO: re-use vertex buffers here? */
+ /* I915_NEW_VBO
+ */
LIS0 = i915->vbo_offset;
- /* I915_NEW_VERTEX_SIZE -- do this where the vertex size is calculated!
+ /* I915_NEW_VERTEX_SIZE
*/
+ /* XXX do this where the vertex size is calculated! */
{
unsigned vertex_size = i915->current.vertex_info.size;
LIS1 = ((vertex_size << 24) |
- (vertex_size << 16));
+ (vertex_size << 16));
}
- /* I915_NEW_VBO */
- /* TODO: use a vertex generation number to track vbo changes */
+ /* I915_NEW_VBO
+ */
if (1 ||
i915->current.immediate[I915_IMMEDIATE_S0] != LIS0 ||
- i915->current.immediate[I915_IMMEDIATE_S1] != LIS1)
+ i915->current.immediate[I915_IMMEDIATE_S1] != LIS1)
{
i915->current.immediate[I915_IMMEDIATE_S0] = LIS0;
i915->current.immediate[I915_IMMEDIATE_S1] = LIS1;
@@ -78,13 +79,13 @@ static void upload_S0S1(struct i915_context *i915)
}
const struct i915_tracked_state i915_upload_S0S1 = {
- I915_NEW_VBO | I915_NEW_VERTEX_FORMAT,
- upload_S0S1
+ "imm S0 S1",
+ upload_S0S1,
+ I915_NEW_VBO | I915_NEW_VERTEX_FORMAT
};
-
/***********************************************************************
* S4: Vertex format, rasterization state
*/
@@ -92,7 +93,8 @@ static void upload_S2S4(struct i915_context *i915)
{
unsigned LIS2, LIS4;
- /* I915_NEW_VERTEX_FORMAT */
+ /* I915_NEW_VERTEX_FORMAT
+ */
{
LIS2 = i915->current.vertex_info.hwfmt[1];
LIS4 = i915->current.vertex_info.hwfmt[0];
@@ -113,35 +115,38 @@ static void upload_S2S4(struct i915_context *i915)
}
}
-
const struct i915_tracked_state i915_upload_S2S4 = {
- I915_NEW_RASTERIZER | I915_NEW_VERTEX_FORMAT,
- upload_S2S4
+ "imm S2 S4",
+ upload_S2S4,
+ I915_NEW_RASTERIZER | I915_NEW_VERTEX_FORMAT
};
/***********************************************************************
- *
*/
-static void upload_S5( struct i915_context *i915 )
+static void upload_S5(struct i915_context *i915)
{
unsigned LIS5 = 0;
+ /* I915_NEW_DEPTH_STENCIL
+ */
LIS5 |= i915->depth_stencil->stencil_LIS5;
/* hope it's safe to set stencil ref value even if stencil test is disabled? */
LIS5 |= i915->stencil_ref.ref_value[0] << S5_STENCIL_REF_SHIFT;
+ /* I915_NEW_BLEND
+ */
LIS5 |= i915->blend->LIS5;
#if 0
- /* I915_NEW_RASTERIZER */
+ /* I915_NEW_RASTERIZER
+ */
if (i915->state.Polygon->OffsetFill) {
LIS5 |= S5_GLOBAL_DEPTH_OFFSET_ENABLE;
}
#endif
-
if (LIS5 != i915->current.immediate[I915_IMMEDIATE_S5]) {
i915->current.immediate[I915_IMMEDIATE_S5] = LIS5;
i915->hardware_dirty |= I915_HW_IMMEDIATE;
@@ -149,14 +154,16 @@ static void upload_S5( struct i915_context *i915 )
}
const struct i915_tracked_state i915_upload_S5 = {
- (I915_NEW_DEPTH_STENCIL | I915_NEW_BLEND | I915_NEW_RASTERIZER),
- upload_S5
+ "imm S5",
+ upload_S5,
+ I915_NEW_DEPTH_STENCIL | I915_NEW_BLEND | I915_NEW_RASTERIZER
};
+
/***********************************************************************
*/
-static void upload_S6( struct i915_context *i915 )
+static void upload_S6(struct i915_context *i915)
{
unsigned LIS6 = (2 << S6_TRISTRIP_PV_SHIFT);
@@ -180,14 +187,16 @@ static void upload_S6( struct i915_context *i915 )
}
const struct i915_tracked_state i915_upload_S6 = {
- I915_NEW_BLEND | I915_NEW_DEPTH_STENCIL | I915_NEW_FRAMEBUFFER,
- upload_S6
+ "imm s6",
+ upload_S6,
+ I915_NEW_BLEND | I915_NEW_DEPTH_STENCIL | I915_NEW_FRAMEBUFFER
};
+
/***********************************************************************
*/
-static void upload_S7( struct i915_context *i915 )
+static void upload_S7(struct i915_context *i915)
{
unsigned LIS7;
@@ -202,11 +211,15 @@ static void upload_S7( struct i915_context *i915 )
}
const struct i915_tracked_state i915_upload_S7 = {
- I915_NEW_RASTERIZER,
- upload_S7
+ "imm S7",
+ upload_S7,
+ I915_NEW_RASTERIZER
};
+
+/***********************************************************************
+ */
static const struct i915_tracked_state *atoms[] = {
&i915_upload_S0S1,
&i915_upload_S2S4,
@@ -215,13 +228,17 @@ static const struct i915_tracked_state *atoms[] = {
&i915_upload_S7
};
-/*
- */
-void i915_update_immediate( struct i915_context *i915 )
+static void update_immediate(struct i915_context *i915)
{
int i;
for (i = 0; i < Elements(atoms); i++)
if (i915->dirty & atoms[i]->dirty)
- atoms[i]->update( i915 );
+ atoms[i]->update(i915);
}
+
+struct i915_tracked_state i915_hw_immediate = {
+ "immediate",
+ update_immediate,
+ ~0 /* all state atoms, becuase we do internal checking */
+};
diff --git a/src/gallium/drivers/i915/i915_state_sampler.c b/src/gallium/drivers/i915/i915_state_sampler.c
index 77b9bccbb7..941259eb76 100644
--- a/src/gallium/drivers/i915/i915_state_sampler.c
+++ b/src/gallium/drivers/i915/i915_state_sampler.c
@@ -53,17 +53,23 @@
*
* So we need to update the map state when we change samplers and
* we need to be change the sampler state when map state is changed.
- * The first part is done by calling i915_update_texture in
- * i915_update_samplers and the second part is done else where in
- * code tracking the state changes.
+ * The first part is done by calling update_texture in update_samplers
+ * and the second part is done else where in code tracking the state
+ * changes.
+ */
+
+static void update_texture(struct i915_context *i915,
+ uint unit,
+ const struct i915_texture *tex,
+ const struct i915_sampler_state *sampler,
+ uint state[6]);
+
+
+
+/***********************************************************************
+ * Samplers
*/
-static void
-i915_update_texture(struct i915_context *i915,
- uint unit,
- const struct i915_texture *tex,
- const struct i915_sampler_state *sampler,
- uint state[6]);
/**
* Compute i915 texture sampling state.
*
@@ -74,16 +80,13 @@ i915_update_texture(struct i915_context *i915,
*/
static void update_sampler(struct i915_context *i915,
uint unit,
- const struct i915_sampler_state *sampler,
- const struct i915_texture *tex,
- unsigned state[3] )
+ const struct i915_sampler_state *sampler,
+ const struct i915_texture *tex,
+ unsigned state[3])
{
const struct pipe_resource *pt = &tex->b.b;
unsigned minlod, lastlod;
- /* Need to do this after updating the maps, which call the
- * intel_finalize_mipmap_tree and hence can update firstLevel:
- */
state[0] = sampler->state[0];
state[1] = sampler->state[1];
state[2] = sampler->state[2];
@@ -118,7 +121,7 @@ static void update_sampler(struct i915_context *i915,
wr == PIPE_TEX_WRAP_CLAMP_TO_BORDER)) {
if (i915->conformance_mode > 0) {
assert(0);
- /* sampler->fallback = true; */
+ /* sampler->fallback = true; */
/* TODO */
}
}
@@ -137,8 +140,7 @@ static void update_sampler(struct i915_context *i915,
state[1] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT);
}
-
-void i915_update_samplers( struct i915_context *i915 )
+static void update_samplers(struct i915_context *i915)
{
uint unit;
@@ -152,29 +154,38 @@ void i915_update_samplers( struct i915_context *i915 )
if (i915->fragment_sampler_views[unit]) {
struct i915_texture *texture = i915_texture(i915->fragment_sampler_views[unit]->texture);
- update_sampler( i915,
- unit,
- i915->sampler[unit], /* sampler state */
- texture, /* texture */
- i915->current.sampler[unit] /* the result */
- );
- i915_update_texture( i915,
- unit,
- texture, /* texture */
- i915->sampler[unit], /* sampler state */
- i915->current.texbuffer[unit] );
-
- i915->current.sampler_enable_nr++;
- i915->current.sampler_enable_flags |= (1 << unit);
+ update_sampler(i915,
+ unit,
+ i915->sampler[unit], /* sampler state */
+ texture, /* texture */
+ i915->current.sampler[unit]); /* the result */
+ update_texture(i915,
+ unit,
+ texture, /* texture */
+ i915->sampler[unit], /* sampler state */
+ i915->current.texbuffer[unit]); /* the result */
+
+ i915->current.sampler_enable_nr++;
+ i915->current.sampler_enable_flags |= (1 << unit);
}
}
i915->hardware_dirty |= I915_HW_SAMPLER | I915_HW_MAP;
}
+struct i915_tracked_state i915_hw_samplers = {
+ "sampler_views",
+ update_samplers,
+ I915_NEW_SAMPLER | I915_NEW_SAMPLER_VIEW
+};
-static uint
-translate_texture_format(enum pipe_format pipeFormat)
+
+
+/***********************************************************************
+ * Sampler views
+ */
+
+static uint translate_texture_format(enum pipe_format pipeFormat)
{
switch (pipeFormat) {
case PIPE_FORMAT_L8_UNORM:
@@ -226,19 +237,17 @@ translate_texture_format(enum pipe_format pipeFormat)
return (MAPSURF_32BIT | MT_32BIT_xI824);
default:
debug_printf("i915: translate_texture_format() bad image format %x\n",
- pipeFormat);
+ pipeFormat);
assert(0);
return 0;
}
}
-
-static void
-i915_update_texture(struct i915_context *i915,
- uint unit,
- const struct i915_texture *tex,
- const struct i915_sampler_state *sampler,
- uint state[6])
+static void update_texture(struct i915_context *i915,
+ uint unit,
+ const struct i915_texture *tex,
+ const struct i915_sampler_state *sampler,
+ uint state[6])
{
const struct pipe_resource *pt = &tex->b.b;
uint format, pitch;
@@ -287,9 +296,7 @@ i915_update_texture(struct i915_context *i915,
| ((depth - 1) << MS4_VOLUME_DEPTH_SHIFT));
}
-
-void
-i915_update_textures(struct i915_context *i915)
+static void update_textures(struct i915_context *i915)
{
uint unit;
@@ -300,13 +307,19 @@ i915_update_textures(struct i915_context *i915)
if (i915->fragment_sampler_views[unit]) {
struct i915_texture *texture = i915_texture(i915->fragment_sampler_views[unit]->texture);
- i915_update_texture( i915,
- unit,
- texture, /* texture */
- i915->sampler[unit], /* sampler state */
- i915->current.texbuffer[unit] );
+ update_texture(i915,
+ unit,
+ texture, /* texture */
+ i915->sampler[unit], /* sampler state */
+ i915->current.texbuffer[unit]);
}
}
i915->hardware_dirty |= I915_HW_MAP;
}
+
+struct i915_tracked_state i915_hw_sampler_views = {
+ "sampler_views",
+ update_textures,
+ I915_NEW_SAMPLER_VIEW
+};
diff --git a/src/gallium/drivers/i965/SConscript b/src/gallium/drivers/i965/SConscript
index 019af682f6..119f914a16 100644
--- a/src/gallium/drivers/i965/SConscript
+++ b/src/gallium/drivers/i965/SConscript
@@ -2,6 +2,10 @@ Import('*')
env = env.Clone()
+if msvc:
+ print 'warning: not building i965g'
+ Return();
+
i965 = env.ConvenienceLibrary(
target = 'i965',
source = [
diff --git a/src/gallium/drivers/i965/brw_disasm.c b/src/gallium/drivers/i965/brw_disasm.c
index 4c8579365d..28c83515ba 100644
--- a/src/gallium/drivers/i965/brw_disasm.c
+++ b/src/gallium/drivers/i965/brw_disasm.c
@@ -239,7 +239,7 @@ char *imm_encoding[8] = {
[2] = "UW",
[3] = "W",
[5] = "VF",
- [5] = "V",
+ [6] = "V",
[7] = "F"
};
diff --git a/src/gallium/drivers/i965/brw_pipe_query.c b/src/gallium/drivers/i965/brw_pipe_query.c
index 2eb862635c..0745254c3c 100644
--- a/src/gallium/drivers/i965/brw_pipe_query.c
+++ b/src/gallium/drivers/i965/brw_pipe_query.c
@@ -50,10 +50,11 @@ static boolean
brw_query_get_result(struct pipe_context *pipe,
struct pipe_query *q,
boolean wait,
- uint64_t *result)
+ void *vresult)
{
struct brw_context *brw = brw_context(pipe);
struct brw_query_object *query = (struct brw_query_object *)q;
+ uint64_t *result = (uint64_t*)vresult;
/* Map and count the pixels from the current query BO */
if (query->bo) {
diff --git a/src/gallium/drivers/identity/id_context.c b/src/gallium/drivers/identity/id_context.c
index 898e0b3af8..67be895b38 100644
--- a/src/gallium/drivers/identity/id_context.c
+++ b/src/gallium/drivers/identity/id_context.c
@@ -158,7 +158,7 @@ static boolean
identity_get_query_result(struct pipe_context *_pipe,
struct pipe_query *query,
boolean wait,
- uint64_t *result)
+ void *result)
{
struct identity_context *id_pipe = identity_context(_pipe);
struct pipe_context *pipe = id_pipe->pipe;
diff --git a/src/gallium/drivers/identity/id_objects.c b/src/gallium/drivers/identity/id_objects.c
index ca4743f9ef..593928f399 100644
--- a/src/gallium/drivers/identity/id_objects.c
+++ b/src/gallium/drivers/identity/id_objects.c
@@ -120,13 +120,14 @@ identity_sampler_view_create(struct identity_context *id_context,
assert(view->texture == id_resource->resource);
- id_view = MALLOC(sizeof(struct identity_sampler_view));
+ id_view = CALLOC_STRUCT(identity_sampler_view);
id_view->base = *view;
id_view->base.reference.count = 1;
id_view->base.texture = NULL;
pipe_resource_reference(&id_view->base.texture, id_resource->resource);
id_view->base.context = id_context->pipe;
+ id_view->sampler_view = view;
return &id_view->base;
error:
@@ -180,8 +181,8 @@ identity_transfer_destroy(struct identity_context *id_context,
struct identity_transfer *id_transfer)
{
pipe_resource_reference(&id_transfer->base.resource, NULL);
- id_transfer->pipe->transfer_destroy(id_context->pipe,
- id_transfer->transfer);
+ id_context->pipe->transfer_destroy(id_context->pipe,
+ id_transfer->transfer);
FREE(id_transfer);
}
diff --git a/src/gallium/drivers/identity/id_objects.h b/src/gallium/drivers/identity/id_objects.h
index 5eea10b0b5..e8deabf4fc 100644
--- a/src/gallium/drivers/identity/id_objects.h
+++ b/src/gallium/drivers/identity/id_objects.h
@@ -65,7 +65,6 @@ struct identity_transfer
{
struct pipe_transfer base;
- struct pipe_context *pipe;
struct pipe_transfer *transfer;
};
diff --git a/src/gallium/drivers/llvmpipe/.gitignore b/src/gallium/drivers/llvmpipe/.gitignore
index a1b6f56e0d..4e0d4c3fc0 100644
--- a/src/gallium/drivers/llvmpipe/.gitignore
+++ b/src/gallium/drivers/llvmpipe/.gitignore
@@ -3,3 +3,4 @@ lp_test_blend
lp_test_conv
lp_test_format
lp_test_printf
+lp_test_sincos
diff --git a/src/gallium/drivers/llvmpipe/Makefile b/src/gallium/drivers/llvmpipe/Makefile
index 213e4c4a99..ee28179c30 100644
--- a/src/gallium/drivers/llvmpipe/Makefile
+++ b/src/gallium/drivers/llvmpipe/Makefile
@@ -34,8 +34,10 @@ C_SOURCES = \
lp_state_clip.c \
lp_state_derived.c \
lp_state_fs.c \
+ lp_state_gs.c \
lp_state_rasterizer.c \
lp_state_sampler.c \
+ lp_state_so.c \
lp_state_surface.c \
lp_state_vertex.c \
lp_state_vs.c \
diff --git a/src/gallium/drivers/llvmpipe/SConscript b/src/gallium/drivers/llvmpipe/SConscript
index a0646692e7..a1ef71da89 100644
--- a/src/gallium/drivers/llvmpipe/SConscript
+++ b/src/gallium/drivers/llvmpipe/SConscript
@@ -57,6 +57,7 @@ llvmpipe = env.ConvenienceLibrary(
'lp_state_gs.c',
'lp_state_rasterizer.c',
'lp_state_sampler.c',
+ 'lp_state_so.c',
'lp_state_surface.c',
'lp_state_vertex.c',
'lp_state_vs.c',
diff --git a/src/gallium/drivers/llvmpipe/lp_context.c b/src/gallium/drivers/llvmpipe/lp_context.c
index 9e88a6e09f..3db4f12ebb 100644
--- a/src/gallium/drivers/llvmpipe/lp_context.c
+++ b/src/gallium/drivers/llvmpipe/lp_context.c
@@ -36,6 +36,7 @@
#include "util/u_inlines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
+#include "util/u_simple_list.h"
#include "lp_clear.h"
#include "lp_context.h"
#include "lp_flush.h"
@@ -94,6 +95,8 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv )
memset(llvmpipe, 0, sizeof *llvmpipe);
+ make_empty_list(&llvmpipe->fs_variants_list);
+
llvmpipe->pipe.winsys = screen->winsys;
llvmpipe->pipe.screen = screen;
llvmpipe->pipe.priv = priv;
@@ -110,6 +113,7 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv )
llvmpipe_init_sampler_funcs(llvmpipe);
llvmpipe_init_query_funcs( llvmpipe );
llvmpipe_init_vertex_funcs(llvmpipe);
+ llvmpipe_init_so_funcs(llvmpipe);
llvmpipe_init_fs_funcs(llvmpipe);
llvmpipe_init_vs_funcs(llvmpipe);
llvmpipe_init_gs_funcs(llvmpipe);
diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h
index cb04d4a4d5..986e604ce7 100644
--- a/src/gallium/drivers/llvmpipe/lp_context.h
+++ b/src/gallium/drivers/llvmpipe/lp_context.h
@@ -38,6 +38,7 @@
#include "lp_tex_sample.h"
#include "lp_jit.h"
#include "lp_setup.h"
+#include "lp_state_fs.h"
struct llvmpipe_vbuf_render;
@@ -62,6 +63,7 @@ struct llvmpipe_context {
const struct lp_vertex_shader *vs;
const struct lp_geometry_shader *gs;
const struct lp_velems_state *velems;
+ const struct lp_so_state *so;
/** Other rendering state */
struct pipe_blend_color blend_color;
@@ -75,6 +77,12 @@ struct llvmpipe_context {
struct pipe_sampler_view *vertex_sampler_views[PIPE_MAX_VERTEX_SAMPLERS];
struct pipe_viewport_state viewport;
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
+ struct {
+ struct llvmpipe_resource *buffer[PIPE_MAX_SO_BUFFERS];
+ int offset[PIPE_MAX_SO_BUFFERS];
+ int so_count[PIPE_MAX_SO_BUFFERS];
+ int num_buffers;
+ } so_target;
unsigned num_samplers;
unsigned num_fragment_sampler_views;
@@ -105,6 +113,8 @@ struct llvmpipe_context {
unsigned tex_timestamp;
boolean no_rast;
+ struct lp_fs_variant_list_item fs_variants_list;
+ unsigned nr_fs_variants;
};
diff --git a/src/gallium/drivers/llvmpipe/lp_limits.h b/src/gallium/drivers/llvmpipe/lp_limits.h
index 4102a9df67..d1c431475d 100644
--- a/src/gallium/drivers/llvmpipe/lp_limits.h
+++ b/src/gallium/drivers/llvmpipe/lp_limits.h
@@ -66,5 +66,10 @@
*/
#define LP_MAX_SCENE_SIZE (512 * 1024 * 1024)
+/**
+ * Max number of shader variants (for all shaders combined,
+ * per context) that will be kept around.
+ */
+#define LP_MAX_SHADER_VARIANTS 1024
#endif /* LP_LIMITS_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_query.c b/src/gallium/drivers/llvmpipe/lp_query.c
index c486442286..c902c04684 100644
--- a/src/gallium/drivers/llvmpipe/lp_query.c
+++ b/src/gallium/drivers/llvmpipe/lp_query.c
@@ -76,10 +76,11 @@ static boolean
llvmpipe_get_query_result(struct pipe_context *pipe,
struct pipe_query *q,
boolean wait,
- uint64_t *result )
+ void *vresult)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
struct llvmpipe_query *pq = llvmpipe_query(q);
+ uint64_t *result = (uint64_t *)vresult;
if (!pq->done) {
lp_setup_flush(llvmpipe->setup, 0);
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c
index 50e44dcb2b..1fadb9cca1 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast.c
@@ -627,7 +627,7 @@ void
lp_rast_begin_query(struct lp_rasterizer_task *task,
const union lp_rast_cmd_arg arg)
{
- /* Reset the the per-task counter */
+ /* Reset the per-task counter */
task->vis_counter = 0;
}
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c
index b6db66fe64..9e319fd9f0 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup.c
@@ -297,6 +297,11 @@ lp_setup_bind_framebuffer( struct lp_setup_context *setup,
*/
set_scene_state( setup, SETUP_FLUSHED );
+ /*
+ * Ensure the old scene is not reused.
+ */
+ assert(!setup->scene);
+
/* Set new state. This will be picked up later when we next need a
* scene.
*/
@@ -326,7 +331,7 @@ lp_setup_clear( struct lp_setup_context *setup,
if (flags & PIPE_CLEAR_DEPTHSTENCIL) {
if (setup->fb.zsbuf &&
- ((setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) &&
+ ((flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) &&
util_format_is_depth_and_stencil(setup->fb.zsbuf->format))
full_zs_clear = FALSE;
@@ -933,6 +938,8 @@ lp_setup_begin_query(struct lp_setup_context *setup,
memset(pq->count, 0, sizeof(pq->count)); /* reset all counters */
+ set_scene_state( setup, SETUP_ACTIVE );
+
cmd_arg.query_obj = pq;
lp_scene_bin_everywhere(scene, lp_rast_begin_query, cmd_arg);
pq->binned = TRUE;
@@ -948,6 +955,8 @@ lp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq)
struct lp_scene * scene = lp_setup_get_current_scene(setup);
union lp_rast_cmd_arg cmd_arg;
+ set_scene_state( setup, SETUP_ACTIVE );
+
cmd_arg.query_obj = pq;
lp_scene_bin_everywhere(scene, lp_rast_end_query, cmd_arg);
}
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c b/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c
index f6a424f25a..e53a62cb72 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c
@@ -60,10 +60,6 @@ static const struct vertex_info *
lp_setup_get_vertex_info(struct vbuf_render *vbr)
{
struct lp_setup_context *setup = lp_setup_context(vbr);
-
- /* vertex size/info depends on the latest state */
- lp_setup_update_state(setup);
-
return setup->vertex_info;
}
diff --git a/src/gallium/drivers/llvmpipe/lp_state.h b/src/gallium/drivers/llvmpipe/lp_state.h
index 3f7a85b682..05d1b93794 100644
--- a/src/gallium/drivers/llvmpipe/lp_state.h
+++ b/src/gallium/drivers/llvmpipe/lp_state.h
@@ -54,6 +54,9 @@
#define LP_NEW_QUERY 0x4000
#define LP_NEW_BLEND_COLOR 0x8000
#define LP_NEW_GS 0x10000
+#define LP_NEW_SO 0x20000
+#define LP_NEW_SO_BUFFERS 0x40000
+
struct vertex_info;
@@ -82,6 +85,10 @@ struct lp_velems_state
struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS];
};
+struct lp_so_state {
+ struct pipe_stream_output_state base;
+};
+
void
llvmpipe_set_framebuffer_state(struct pipe_context *,
@@ -120,5 +127,9 @@ llvmpipe_init_gs_funcs(struct llvmpipe_context *llvmpipe);
void
llvmpipe_init_rasterizer_funcs(struct llvmpipe_context *llvmpipe);
+void
+llvmpipe_init_so_funcs(struct llvmpipe_context *llvmpipe);
+
+
#endif
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
index 2619e043fd..65115052cd 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -68,6 +68,7 @@
#include "util/u_format.h"
#include "util/u_dump.h"
#include "util/u_string.h"
+#include "util/u_simple_list.h"
#include "os/os_time.h"
#include "pipe/p_shader_tokens.h"
#include "draw/draw_context.h"
@@ -95,6 +96,7 @@
#include "lp_setup.h"
#include "lp_state.h"
#include "lp_tex_sample.h"
+#include "lp_flush.h"
#include <llvm-c/Analysis.h>
@@ -936,7 +938,10 @@ generate_variant(struct llvmpipe_context *lp,
if(!variant)
return NULL;
- variant->no = shader->variant_no++;
+ variant->shader = shader;
+ variant->list_item_global.base = variant;
+ variant->list_item_local.base = variant;
+ variant->no = shader->variants_created++;
memcpy(&variant->key, key, sizeof *key);
@@ -962,10 +967,6 @@ generate_variant(struct llvmpipe_context *lp,
!shader->info.uses_kill
? TRUE : FALSE;
- /* insert new variant into linked list */
- variant->next = shader->variants;
- shader->variants = variant;
-
return variant;
}
@@ -981,6 +982,7 @@ llvmpipe_create_fs_state(struct pipe_context *pipe,
return NULL;
shader->no = fs_no++;
+ make_empty_list(&shader->variants);
/* get/save the summary info for this shader */
tgsi_scan_shader(templ->tokens, &shader->info);
@@ -1024,14 +1026,40 @@ llvmpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
llvmpipe->dirty |= LP_NEW_FS;
}
+static void
+remove_shader_variant(struct llvmpipe_context *lp,
+ struct lp_fragment_shader_variant *variant)
+{
+ struct llvmpipe_screen *screen = llvmpipe_screen(lp->pipe.screen);
+ unsigned i;
+
+ if (gallivm_debug & GALLIVM_DEBUG_IR) {
+ debug_printf("llvmpipe: del fs #%u var #%u v created #%u v cached #%u v total cached #%u\n",
+ variant->shader->no, variant->no, variant->shader->variants_created,
+ variant->shader->variants_cached, lp->nr_fs_variants);
+ }
+ for (i = 0; i < Elements(variant->function); i++) {
+ if (variant->function[i]) {
+ if (variant->jit_function[i])
+ LLVMFreeMachineCodeForFunction(screen->engine,
+ variant->function[i]);
+ LLVMDeleteFunction(variant->function[i]);
+ }
+ }
+ remove_from_list(&variant->list_item_local);
+ variant->shader->variants_cached--;
+ remove_from_list(&variant->list_item_global);
+ lp->nr_fs_variants--;
+ FREE(variant);
+}
static void
llvmpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
- struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
+ struct pipe_fence_handle *fence = NULL;
struct lp_fragment_shader *shader = fs;
- struct lp_fragment_shader_variant *variant;
+ struct lp_fs_variant_list_item *li;
assert(fs != llvmpipe->fs);
(void) llvmpipe;
@@ -1039,29 +1067,24 @@ llvmpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
/*
* XXX: we need to flush the context until we have some sort of reference
* counting in fragment shaders as they may still be binned
+ * Flushing alone might not sufficient we need to wait on it too.
*/
- draw_flush(llvmpipe->draw);
- lp_setup_flush(llvmpipe->setup, 0);
-
- variant = shader->variants;
- while(variant) {
- struct lp_fragment_shader_variant *next = variant->next;
- unsigned i;
- for (i = 0; i < Elements(variant->function); i++) {
- if (variant->function[i]) {
- if (variant->jit_function[i])
- LLVMFreeMachineCodeForFunction(screen->engine,
- variant->function[i]);
- LLVMDeleteFunction(variant->function[i]);
- }
- }
+ llvmpipe_flush(pipe, 0, &fence);
- FREE(variant);
+ if (fence) {
+ pipe->screen->fence_finish(pipe->screen, fence, 0);
+ pipe->screen->fence_reference(pipe->screen, &fence, NULL);
+ }
- variant = next;
+ li = first_elem(&shader->variants);
+ while(!at_end(&shader->variants, li)) {
+ struct lp_fs_variant_list_item *next = next_elem(li);
+ remove_shader_variant(llvmpipe, li->base);
+ li = next;
}
+ assert(shader->variants_cached == 0);
FREE((void *) shader->base.tokens);
FREE(shader);
}
@@ -1088,9 +1111,10 @@ llvmpipe_set_constant_buffer(struct pipe_context *pipe,
/* note: reference counting */
pipe_resource_reference(&llvmpipe->constants[shader][index], constants);
- if(shader == PIPE_SHADER_VERTEX) {
- draw_set_mapped_constant_buffer(llvmpipe->draw, PIPE_SHADER_VERTEX, index,
- data, size);
+ if(shader == PIPE_SHADER_VERTEX ||
+ shader == PIPE_SHADER_GEOMETRY) {
+ draw_set_mapped_constant_buffer(llvmpipe->draw, shader,
+ index, data, size);
}
llvmpipe->dirty |= LP_NEW_CONSTANTS;
@@ -1215,7 +1239,6 @@ make_variant_key(struct llvmpipe_context *lp,
lp_sampler_static_state(&key->sampler[i], lp->fragment_sampler_views[i], lp->sampler[i]);
}
-
/**
* Update fragment state. This is called just prior to drawing
* something when some fragment-related state has changed.
@@ -1225,21 +1248,47 @@ llvmpipe_update_fs(struct llvmpipe_context *lp)
{
struct lp_fragment_shader *shader = lp->fs;
struct lp_fragment_shader_variant_key key;
- struct lp_fragment_shader_variant *variant;
+ struct lp_fragment_shader_variant *variant = NULL;
+ struct lp_fs_variant_list_item *li;
make_variant_key(lp, shader, &key);
- variant = shader->variants;
- while(variant) {
- if(memcmp(&variant->key, &key, sizeof key) == 0)
+ li = first_elem(&shader->variants);
+ while(!at_end(&shader->variants, li)) {
+ if(memcmp(&li->base->key, &key, sizeof key) == 0) {
+ variant = li->base;
break;
-
- variant = variant->next;
+ }
+ li = next_elem(li);
}
- if (!variant) {
+ if (variant) {
+ move_to_head(&lp->fs_variants_list, &variant->list_item_global);
+ }
+ else {
int64_t t0, t1;
int64_t dt;
+ unsigned i;
+ if (lp->nr_fs_variants >= LP_MAX_SHADER_VARIANTS) {
+ struct pipe_context *pipe = &lp->pipe;
+ struct pipe_fence_handle *fence = NULL;
+
+ /*
+ * XXX: we need to flush the context until we have some sort of reference
+ * counting in fragment shaders as they may still be binned
+ * Flushing alone might not be sufficient we need to wait on it too.
+ */
+ llvmpipe_flush(pipe, 0, &fence);
+
+ if (fence) {
+ pipe->screen->fence_finish(pipe->screen, fence, 0);
+ pipe->screen->fence_reference(pipe->screen, &fence, NULL);
+ }
+ for (i = 0; i < LP_MAX_SHADER_VARIANTS / 4; i++) {
+ struct lp_fs_variant_list_item *item = last_elem(&lp->fs_variants_list);
+ remove_shader_variant(lp, item->base);
+ }
+ }
t0 = os_time_get();
variant = generate_variant(lp, shader, &key);
@@ -1248,6 +1297,13 @@ llvmpipe_update_fs(struct llvmpipe_context *lp)
dt = t1 - t0;
LP_COUNT_ADD(llvm_compile_time, dt);
LP_COUNT_ADD(nr_llvm_compiles, 2); /* emit vs. omit in/out test */
+
+ if (variant) {
+ insert_at_head(&shader->variants, &variant->list_item_local);
+ insert_at_head(&lp->fs_variants_list, &variant->list_item_global);
+ lp->nr_fs_variants++;
+ shader->variants_cached++;
+ }
}
lp_setup_set_fs_variant(lp->setup, variant);
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.h b/src/gallium/drivers/llvmpipe/lp_state_fs.h
index 64ead2a997..593cd4de6b 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.h
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.h
@@ -64,6 +64,11 @@ struct lp_fragment_shader_variant_key
struct lp_sampler_static_state sampler[PIPE_MAX_SAMPLERS];
};
+struct lp_fs_variant_list_item
+{
+ struct lp_fragment_shader_variant *base;
+ struct lp_fs_variant_list_item *next, *prev;
+};
struct lp_fragment_shader_variant
{
@@ -75,7 +80,8 @@ struct lp_fragment_shader_variant
lp_jit_frag_func jit_function[2];
- struct lp_fragment_shader_variant *next;
+ struct lp_fs_variant_list_item list_item_global, list_item_local;
+ struct lp_fragment_shader *shader;
/* For debugging/profiling purposes */
unsigned no;
@@ -89,11 +95,12 @@ struct lp_fragment_shader
struct tgsi_shader_info info;
- struct lp_fragment_shader_variant *variants;
+ struct lp_fs_variant_list_item variants;
/* For debugging/profiling purposes */
unsigned no;
- unsigned variant_no;
+ unsigned variants_created;
+ unsigned variants_cached;
};
diff --git a/src/gallium/drivers/llvmpipe/lp_state_gs.c b/src/gallium/drivers/llvmpipe/lp_state_gs.c
index e5eeb88e2b..1ba6f10821 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_gs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_gs.c
@@ -33,7 +33,6 @@
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "draw/draw_context.h"
-#include "draw/draw_vs.h"
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_scan.h"
#include "tgsi/tgsi_parse.h"
diff --git a/src/gallium/drivers/llvmpipe/lp_state_sampler.c b/src/gallium/drivers/llvmpipe/lp_state_sampler.c
index 55d43368a3..e94065fb6a 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_sampler.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_sampler.c
@@ -105,6 +105,13 @@ llvmpipe_bind_vertex_sampler_states(struct pipe_context *pipe,
static void
+llvmpipe_bind_geometry_sampler_states(struct pipe_context *pipe,
+ unsigned num, void **sampler)
+{
+ /* XXX: implementation missing */
+}
+
+static void
llvmpipe_set_fragment_sampler_views(struct pipe_context *pipe,
unsigned num,
struct pipe_sampler_view **views)
@@ -163,6 +170,14 @@ llvmpipe_set_vertex_sampler_views(struct pipe_context *pipe,
}
+static void
+llvmpipe_set_geometry_sampler_views(struct pipe_context *pipe,
+ unsigned num,
+ struct pipe_sampler_view **views)
+{
+ /*XXX: implementation missing */
+}
+
static struct pipe_sampler_view *
llvmpipe_create_sampler_view(struct pipe_context *pipe,
struct pipe_resource *texture,
@@ -206,8 +221,10 @@ llvmpipe_init_sampler_funcs(struct llvmpipe_context *llvmpipe)
llvmpipe->pipe.bind_fragment_sampler_states = llvmpipe_bind_sampler_states;
llvmpipe->pipe.bind_vertex_sampler_states = llvmpipe_bind_vertex_sampler_states;
+ llvmpipe->pipe.bind_geometry_sampler_states = llvmpipe_bind_geometry_sampler_states;
llvmpipe->pipe.set_fragment_sampler_views = llvmpipe_set_fragment_sampler_views;
llvmpipe->pipe.set_vertex_sampler_views = llvmpipe_set_vertex_sampler_views;
+ llvmpipe->pipe.set_geometry_sampler_views = llvmpipe_set_geometry_sampler_views;
llvmpipe->pipe.create_sampler_view = llvmpipe_create_sampler_view;
llvmpipe->pipe.sampler_view_destroy = llvmpipe_sampler_view_destroy;
llvmpipe->pipe.delete_sampler_state = llvmpipe_delete_sampler_state;
diff --git a/src/gallium/drivers/llvmpipe/lp_state_so.c b/src/gallium/drivers/llvmpipe/lp_state_so.c
new file mode 100644
index 0000000000..30b17c9881
--- /dev/null
+++ b/src/gallium/drivers/llvmpipe/lp_state_so.c
@@ -0,0 +1,137 @@
+/**************************************************************************
+ *
+ * Copyright 2010 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "lp_context.h"
+#include "lp_state.h"
+#include "lp_texture.h"
+
+#include "util/u_memory.h"
+#include "draw/draw_context.h"
+
+
+static void *
+llvmpipe_create_stream_output_state(struct pipe_context *pipe,
+ const struct pipe_stream_output_state *templ)
+{
+ struct lp_so_state *so;
+ so = (struct lp_so_state *) CALLOC_STRUCT(lp_so_state);
+
+ if (so) {
+ so->base.num_outputs = templ->num_outputs;
+ so->base.stride = templ->stride;
+ memcpy(so->base.output_buffer,
+ templ->output_buffer,
+ sizeof(int) * templ->num_outputs);
+ memcpy(so->base.register_index,
+ templ->register_index,
+ sizeof(int) * templ->num_outputs);
+ memcpy(so->base.register_mask,
+ templ->register_mask,
+ sizeof(ubyte) * templ->num_outputs);
+ }
+ return so;
+}
+
+static void
+llvmpipe_bind_stream_output_state(struct pipe_context *pipe,
+ void *so)
+{
+ struct llvmpipe_context *lp = llvmpipe_context(pipe);
+ struct lp_so_state *lp_so = (struct lp_so_state *) so;
+
+ lp->so = lp_so;
+
+ lp->dirty |= LP_NEW_SO;
+
+ if (lp_so)
+ draw_set_so_state(lp->draw, &lp_so->base);
+}
+
+static void
+llvmpipe_delete_stream_output_state(struct pipe_context *pipe, void *so)
+{
+ FREE( so );
+}
+
+static void
+llvmpipe_set_stream_output_buffers(struct pipe_context *pipe,
+ struct pipe_resource **buffers,
+ int *offsets,
+ int num_buffers)
+{
+ struct llvmpipe_context *lp = llvmpipe_context(pipe);
+ int i;
+ void *map_buffers[PIPE_MAX_SO_BUFFERS];
+
+ assert(num_buffers <= PIPE_MAX_SO_BUFFERS);
+ if (num_buffers > PIPE_MAX_SO_BUFFERS)
+ num_buffers = PIPE_MAX_SO_BUFFERS;
+
+ lp->dirty |= LP_NEW_SO_BUFFERS;
+
+ for (i = 0; i < num_buffers; ++i) {
+ void *mapped;
+ struct llvmpipe_resource *res = llvmpipe_resource(buffers[i]);
+
+ if (!res) {
+ /* the whole call is invalid, bail out */
+ lp->so_target.num_buffers = 0;
+ draw_set_mapped_so_buffers(lp->draw, 0, 0);
+ return;
+ }
+
+ lp->so_target.buffer[i] = res;
+ lp->so_target.offset[i] = offsets[i];
+ lp->so_target.so_count[i] = 0;
+
+ mapped = res->data;
+ if (offsets[i] >= 0)
+ map_buffers[i] = ((char*)mapped) + offsets[i];
+ else {
+ /* this is a buffer append */
+ assert(!"appending not implemented");
+ map_buffers[i] = mapped;
+ }
+ }
+ lp->so_target.num_buffers = num_buffers;
+
+ draw_set_mapped_so_buffers(lp->draw, map_buffers, num_buffers);
+}
+
+void
+llvmpipe_init_so_funcs(struct llvmpipe_context *llvmpipe)
+{
+ llvmpipe->pipe.create_stream_output_state =
+ llvmpipe_create_stream_output_state;
+ llvmpipe->pipe.bind_stream_output_state =
+ llvmpipe_bind_stream_output_state;
+ llvmpipe->pipe.delete_stream_output_state =
+ llvmpipe_delete_stream_output_state;
+
+ llvmpipe->pipe.set_stream_output_buffers =
+ llvmpipe_set_stream_output_buffers;
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_surface.c b/src/gallium/drivers/llvmpipe/lp_surface.c
index 4f409f9b63..f0cbbe8c56 100644
--- a/src/gallium/drivers/llvmpipe/lp_surface.c
+++ b/src/gallium/drivers/llvmpipe/lp_surface.c
@@ -67,14 +67,14 @@ lp_resource_copy(struct pipe_context *pipe,
dst, subdst.face, subdst.level,
0, /* flush_flags */
FALSE, /* read_only */
- FALSE, /* cpu_access */
+ TRUE, /* cpu_access */
FALSE); /* do_not_block */
llvmpipe_flush_resource(pipe,
src, subsrc.face, subsrc.level,
0, /* flush_flags */
TRUE, /* read_only */
- FALSE, /* cpu_access */
+ TRUE, /* cpu_access */
FALSE); /* do_not_block */
/*
@@ -106,19 +106,27 @@ lp_resource_copy(struct pipe_context *pipe,
unsigned x, y;
enum lp_texture_usage usage;
- /* XXX for the tiles which are completely contained by the
- * dest rectangle, we could set the usage mode to WRITE_ALL.
- * Just test for the case of replacing the whole dest region for now.
- */
- if (width == dst_tex->base.width0 && height == dst_tex->base.height0)
- usage = LP_TEX_USAGE_WRITE_ALL;
- else
- usage = LP_TEX_USAGE_READ_WRITE;
-
adjust_to_tile_bounds(dstx, dsty, width, height, &tx, &ty, &tw, &th);
for (y = 0; y < th; y += TILE_SIZE) {
+ boolean contained_y = ty + y >= dsty &&
+ ty + y + TILE_SIZE <= dsty + height ?
+ TRUE : FALSE;
+
for (x = 0; x < tw; x += TILE_SIZE) {
+ boolean contained_x = tx + x >= dstx &&
+ tx + x + TILE_SIZE <= dstx + width ?
+ TRUE : FALSE;
+
+ /*
+ * Set the usage mode to WRITE_ALL for the tiles which are
+ * completely contained by the dest rectangle.
+ */
+ if (contained_y && contained_x)
+ usage = LP_TEX_USAGE_WRITE_ALL;
+ else
+ usage = LP_TEX_USAGE_READ_WRITE;
+
(void) llvmpipe_get_texture_tile_linear(dst_tex,
subdst.face, subdst.level,
usage,
@@ -153,4 +161,6 @@ void
llvmpipe_init_surface_functions(struct llvmpipe_context *lp)
{
lp->pipe.resource_copy_region = lp_resource_copy;
+ lp->pipe.clear_render_target = util_clear_render_target;
+ lp->pipe.clear_depth_stencil = util_clear_depth_stencil;
}
diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c
index 97f938e698..8cb1639013 100644
--- a/src/gallium/drivers/nv50/nv50_program.c
+++ b/src/gallium/drivers/nv50/nv50_program.c
@@ -3924,7 +3924,7 @@ ctor_nv50_pc(struct nv50_pc *pc, struct nv50_program *p)
case TGSI_PROPERTY_GS_OUTPUT_PRIM:
p->cfg.prim_type = nv50_map_gs_output_prim(data[0]);
break;
- case TGSI_PROPERTY_GS_MAX_VERTICES:
+ case TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES:
p->cfg.vert_count = data[0];
break;
default:
diff --git a/src/gallium/drivers/nv50/nv50_query.c b/src/gallium/drivers/nv50/nv50_query.c
index 57b16a355d..53f94820ce 100644
--- a/src/gallium/drivers/nv50/nv50_query.c
+++ b/src/gallium/drivers/nv50/nv50_query.c
@@ -106,8 +106,9 @@ nv50_query_end(struct pipe_context *pipe, struct pipe_query *pq)
static boolean
nv50_query_result(struct pipe_context *pipe, struct pipe_query *pq,
- boolean wait, uint64_t *result)
+ boolean wait, void *vresult)
{
+ uint64_t *result = (uint64_t*)vresult;
struct nv50_query *q = nv50_query(pq);
int ret;
diff --git a/src/gallium/drivers/nv50/nv50_surface.c b/src/gallium/drivers/nv50/nv50_surface.c
index 814921f764..3e61203adf 100644
--- a/src/gallium/drivers/nv50/nv50_surface.c
+++ b/src/gallium/drivers/nv50/nv50_surface.c
@@ -115,7 +115,6 @@ nv50_surface_set(struct nv50_screen *screen, struct pipe_surface *ps, int dst)
}
if (!bo->tile_flags) {
- MARK_RING (chan, 9, 2); /* flush on lack of space or relocs */
BEGIN_RING(chan, eng2d, mthd, 2);
OUT_RING (chan, format);
OUT_RING (chan, 1);
@@ -126,7 +125,6 @@ nv50_surface_set(struct nv50_screen *screen, struct pipe_surface *ps, int dst)
OUT_RELOCh(chan, bo, ps->offset, flags);
OUT_RELOCl(chan, bo, ps->offset, flags);
} else {
- MARK_RING (chan, 11, 2); /* flush on lack of space or relocs */
BEGIN_RING(chan, eng2d, mthd, 5);
OUT_RING (chan, format);
OUT_RING (chan, 0);
@@ -162,7 +160,9 @@ nv50_surface_do_copy(struct nv50_screen *screen, struct pipe_surface *dst,
struct nouveau_grobj *eng2d = screen->eng2d;
int ret;
- WAIT_RING (chan, 32);
+ ret = MARK_RING(chan, 2*16 + 32, 4);
+ if (ret)
+ return ret;
ret = nv50_surface_set(screen, dst, 1);
if (ret)
@@ -209,7 +209,7 @@ nv50_surface_copy(struct pipe_context *pipe,
(nv50_2d_format_faithful(src->format) &&
nv50_2d_format_faithful(dest->format)));
- ps_src = nv50_miptree_surface_new(pipe->screen, dest, subsrc.face,
+ ps_src = nv50_miptree_surface_new(pipe->screen, src, subsrc.face,
subsrc.level, srcz, 0 /* bind flags */);
ps_dst = nv50_miptree_surface_new(pipe->screen, dest, subdst.face,
subdst.level, destz, 0 /* bindflags */);
@@ -241,7 +241,9 @@ nv50_clear_render_target(struct pipe_context *pipe,
if (format < 0)
return;
- WAIT_RING (chan, 32);
+ ret = MARK_RING (chan, 16 + 32, 2);
+ if (ret)
+ return;
ret = nv50_surface_set(screen, dst, 1);
if (ret)
diff --git a/src/gallium/drivers/nvfx/nvfx_query.c b/src/gallium/drivers/nvfx/nvfx_query.c
index 1b20b5245d..1dab20c41a 100644
--- a/src/gallium/drivers/nvfx/nvfx_query.c
+++ b/src/gallium/drivers/nvfx/nvfx_query.c
@@ -96,8 +96,9 @@ nvfx_query_end(struct pipe_context *pipe, struct pipe_query *pq)
static boolean
nvfx_query_result(struct pipe_context *pipe, struct pipe_query *pq,
- boolean wait, uint64_t *result)
+ boolean wait, void *vresult)
{
+ uint64_t *result = (uint64_t *)vresult;
struct nvfx_context *nvfx = nvfx_context(pipe);
struct nvfx_query *q = nvfx_query(pq);
diff --git a/src/gallium/drivers/nvfx/nvfx_surface.c b/src/gallium/drivers/nvfx/nvfx_surface.c
index 44e1af2e6a..a605d2b754 100644
--- a/src/gallium/drivers/nvfx/nvfx_surface.c
+++ b/src/gallium/drivers/nvfx/nvfx_surface.c
@@ -44,7 +44,7 @@ nvfx_surface_copy(struct pipe_context *pipe,
struct nv04_surface_2d *eng2d = nvfx->screen->eng2d;
struct pipe_surface *ps_dst, *ps_src;
- ps_src = nvfx_miptree_surface_new(pipe->screen, dest, subsrc.face,
+ ps_src = nvfx_miptree_surface_new(pipe->screen, src, subsrc.face,
subsrc.level, srcz, 0 /* bind flags */);
ps_dst = nvfx_miptree_surface_new(pipe->screen, dest, subdst.face,
subdst.level, destz, 0 /* bindflags */);
diff --git a/src/gallium/drivers/r300/Makefile b/src/gallium/drivers/r300/Makefile
index 6bb82e5ed0..13152635a6 100644
--- a/src/gallium/drivers/r300/Makefile
+++ b/src/gallium/drivers/r300/Makefile
@@ -14,12 +14,13 @@ C_SOURCES = \
r300_hyperz.c \
r300_query.c \
r300_render.c \
+ r300_render_stencilref.c \
+ r300_render_translate.c \
r300_resource.c \
r300_screen.c \
r300_screen_buffer.c \
r300_state.c \
r300_state_derived.c \
- r300_state_invariant.c \
r300_vs.c \
r300_vs_draw.c \
r300_texture.c \
diff --git a/src/gallium/drivers/r300/SConscript b/src/gallium/drivers/r300/SConscript
index eb3e1d365e..552ed4e5be 100644
--- a/src/gallium/drivers/r300/SConscript
+++ b/src/gallium/drivers/r300/SConscript
@@ -24,12 +24,13 @@ r300 = env.ConvenienceLibrary(
'r300_hyperz.c',
'r300_query.c',
'r300_render.c',
+ 'r300_render_stencilref.c',
+ 'r300_render_translate.c',
'r300_resource.c',
'r300_screen.c',
'r300_screen_buffer.c',
'r300_state.c',
'r300_state_derived.c',
- 'r300_state_invariant.c',
'r300_vs.c',
'r300_vs_draw.c',
'r300_texture.c',
diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c
index 49ec51fd13..97d53a14f8 100644
--- a/src/gallium/drivers/r300/r300_blit.c
+++ b/src/gallium/drivers/r300/r300_blit.c
@@ -25,8 +25,23 @@
#include "util/u_format.h"
-static void r300_blitter_save_states(struct r300_context* r300)
+enum r300_blitter_op /* bitmask */
{
+ R300_CLEAR = 1,
+ R300_CLEAR_SURFACE = 2,
+ R300_COPY = 4
+};
+
+static void r300_blitter_begin(struct r300_context* r300, enum r300_blitter_op op)
+{
+ if (r300->query_current) {
+ r300->blitter_saved_query = r300->query_current;
+ r300_stop_query(r300);
+ }
+
+ /* Yeah we have to save all those states to ensure the blitter operation
+ * is really transparent. The states will be restored by the blitter once
+ * copying is done. */
util_blitter_save_blend(r300->blitter, r300->blend_state.state);
util_blitter_save_depth_stencil_alpha(r300->blitter, r300->dsa_state.state);
util_blitter_save_stencil_ref(r300->blitter, &(r300->stencil_ref));
@@ -34,11 +49,34 @@ static void r300_blitter_save_states(struct r300_context* r300)
util_blitter_save_fragment_shader(r300->blitter, r300->fs.state);
util_blitter_save_vertex_shader(r300->blitter, r300->vs_state.state);
util_blitter_save_viewport(r300->blitter, &r300->viewport);
- util_blitter_save_clip(r300->blitter, &r300->clip);
+ util_blitter_save_clip(r300->blitter, (struct pipe_clip_state*)r300->clip_state.state);
util_blitter_save_vertex_elements(r300->blitter, r300->velems);
- /* XXX this crashes the driver
util_blitter_save_vertex_buffers(r300->blitter, r300->vertex_buffer_count,
- r300->vertex_buffer); */
+ r300->vertex_buffer);
+
+ if (op & (R300_CLEAR_SURFACE | R300_COPY))
+ util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state);
+
+ if (op & R300_COPY) {
+ struct r300_textures_state* state =
+ (struct r300_textures_state*)r300->textures_state.state;
+
+ util_blitter_save_fragment_sampler_states(
+ r300->blitter, state->sampler_state_count,
+ (void**)state->sampler_states);
+
+ util_blitter_save_fragment_sampler_views(
+ r300->blitter, state->sampler_view_count,
+ (struct pipe_sampler_view**)state->sampler_views);
+ }
+}
+
+static void r300_blitter_end(struct r300_context *r300)
+{
+ if (r300->blitter_saved_query) {
+ r300_resume_query(r300, r300->blitter_saved_query);
+ r300->blitter_saved_query = NULL;
+ }
}
/* Clear currently bound buffers. */
@@ -48,24 +86,37 @@ static void r300_clear(struct pipe_context* pipe,
double depth,
unsigned stencil)
{
- /* XXX Implement fastfill.
+ /* My notes about fastfill:
+ *
+ * 1) Only the zbuffer is cleared.
+ *
+ * 2) The zbuffer must be micro-tiled and whole microtiles must be
+ * written. If microtiling is disabled, it locks up.
*
- * If fastfill is enabled, a few facts should be considered:
+ * 3) There is Z Mask RAM which contains a compressed zbuffer and
+ * it interacts with fastfill. We should figure out how to use it
+ * to get more performance.
+ * This is what we know about the Z Mask:
*
- * 1) Zbuffer must be micro-tiled and whole microtiles must be
- * written.
+ * Each dword of the Z Mask contains compression information
+ * for 16 4x4 pixel blocks, that is 2 bits for each block.
+ * On chips with 2 Z pipes, every other dword maps to a different
+ * pipe.
*
- * 2) ZB_DEPTHCLEARVALUE is used to clear a zbuffer and Z Mask must be
- * equal to 0.
+ * 4) ZB_DEPTHCLEARVALUE is used to clear the zbuffer and the Z Mask must
+ * be equal to 0. (clear the Z Mask RAM with zeros)
*
- * 3) For 16-bit integer buffering, compression causes a hung with one or
+ * 5) For 16-bit zbuffer, compression causes a hung with one or
* two samples and should not be used.
*
- * 4) Fastfill must not be used if reading of compressed Z data is disabled
+ * 6) FORCE_COMPRESSED_STENCIL_VALUE should be enabled for stencil clears
+ * to avoid needless decompression.
+ *
+ * 7) Fastfill must not be used if reading of compressed Z data is disabled
* and writing of compressed Z data is enabled (RD/WR_COMP_ENABLE),
* i.e. it cannot be used to compress the zbuffer.
- * (what the hell does that mean and how does it fit in clearing
- * the buffers?)
+ *
+ * 8) ZB_CB_CLEAR does not interact with fastfill in any way.
*
* - Marek
*/
@@ -74,13 +125,45 @@ static void r300_clear(struct pipe_context* pipe,
struct pipe_framebuffer_state* fb =
(struct pipe_framebuffer_state*)r300->fb_state.state;
- r300_blitter_save_states(r300);
-
+ r300_blitter_begin(r300, R300_CLEAR);
util_blitter_clear(r300->blitter,
fb->width,
fb->height,
fb->nr_cbufs,
buffers, rgba, depth, stencil);
+ r300_blitter_end(r300);
+}
+
+/* Clear a region of a color surface to a constant value. */
+static void r300_clear_render_target(struct pipe_context *pipe,
+ struct pipe_surface *dst,
+ const float *rgba,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height)
+{
+ struct r300_context *r300 = r300_context(pipe);
+
+ r300_blitter_begin(r300, R300_CLEAR_SURFACE);
+ util_blitter_clear_render_target(r300->blitter, dst, rgba,
+ dstx, dsty, width, height);
+ r300_blitter_end(r300);
+}
+
+/* Clear a region of a depth stencil surface. */
+static void r300_clear_depth_stencil(struct pipe_context *pipe,
+ struct pipe_surface *dst,
+ unsigned clear_flags,
+ double depth,
+ unsigned stencil,
+ unsigned dstx, unsigned dsty,
+ unsigned width, unsigned height)
+{
+ struct r300_context *r300 = r300_context(pipe);
+
+ r300_blitter_begin(r300, R300_CLEAR_SURFACE);
+ util_blitter_clear_depth_stencil(r300->blitter, dst, clear_flags, depth, stencil,
+ dstx, dsty, width, height);
+ r300_blitter_end(r300);
}
/* Copy a block of pixels from one surface to another using HW. */
@@ -94,27 +177,12 @@ static void r300_hw_copy_region(struct pipe_context* pipe,
unsigned width, unsigned height)
{
struct r300_context* r300 = r300_context(pipe);
- struct r300_textures_state* state =
- (struct r300_textures_state*)r300->textures_state.state;
- /* Yeah we have to save all those states to ensure this blitter operation
- * is really transparent. The states will be restored by the blitter once
- * copying is done. */
- r300_blitter_save_states(r300);
- util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state);
-
- util_blitter_save_fragment_sampler_states(
- r300->blitter, state->sampler_state_count,
- (void**)state->sampler_states);
-
- util_blitter_save_fragment_sampler_views(
- r300->blitter, state->sampler_view_count,
- (struct pipe_sampler_view**)state->sampler_views);
-
- /* Do a copy */
+ r300_blitter_begin(r300, R300_COPY);
util_blitter_copy_region(r300->blitter, dst, subdst, dstx, dsty, dstz,
src, subsrc, srcx, srcy, srcz, width, height,
TRUE);
+ r300_blitter_end(r300);
}
/* Copy a block of pixels from one surface to another. */
@@ -130,14 +198,6 @@ static void r300_resource_copy_region(struct pipe_context *pipe,
enum pipe_format old_format = dst->format;
enum pipe_format new_format = old_format;
- if (dst->format != src->format) {
- debug_printf("r300: Implementation error: Format mismatch in %s\n"
- " : src: %s dst: %s\n", __FUNCTION__,
- util_format_short_name(src->format),
- util_format_short_name(dst->format));
- debug_assert(0);
- }
-
if (!pipe->screen->is_format_supported(pipe->screen,
old_format, src->target,
src->nr_samples,
@@ -188,40 +248,6 @@ static void r300_resource_copy_region(struct pipe_context *pipe,
}
}
-/* Clear a region of a color surface to a constant value. */
-static void r300_clear_render_target(struct pipe_context *pipe,
- struct pipe_surface *dst,
- const float *rgba,
- unsigned dstx, unsigned dsty,
- unsigned width, unsigned height)
-{
- struct r300_context *r300 = r300_context(pipe);
-
- r300_blitter_save_states(r300);
- util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state);
-
- util_blitter_clear_render_target(r300->blitter, dst, rgba,
- dstx, dsty, width, height);
-}
-
-/* Clear a region of a depth stencil surface. */
-static void r300_clear_depth_stencil(struct pipe_context *pipe,
- struct pipe_surface *dst,
- unsigned clear_flags,
- double depth,
- unsigned stencil,
- unsigned dstx, unsigned dsty,
- unsigned width, unsigned height)
-{
- struct r300_context *r300 = r300_context(pipe);
-
- r300_blitter_save_states(r300);
- util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state);
-
- util_blitter_clear_depth_stencil(r300->blitter, dst, clear_flags, depth, stencil,
- dstx, dsty, width, height);
-}
-
void r300_init_blit_functions(struct r300_context *r300)
{
r300->context.clear = r300_clear;
diff --git a/src/gallium/drivers/r300/r300_cb.h b/src/gallium/drivers/r300/r300_cb.h
new file mode 100644
index 0000000000..61b28330b0
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_cb.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Copyright 2010 Marek Olšák <maraeo@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/**
+ * This file contains macros for building command buffers in memory.
+ *
+ * Use NEW_CB for buffers with a varying size and it will also allocate
+ * the buffer.
+ * Use BEGIN_CB for arrays with a static size.
+ *
+ * Example:
+ *
+ * uint32_t cb[3];
+ * CB_LOCALS;
+ *
+ * BEGIN_CB(cb, 3);
+ * OUT_CB_REG_SEQ(R500_RB3D_CONSTANT_COLOR_AR, 2);
+ * OUT_CB(blend_color_red_alpha);
+ * OUT_CB(blend_color_green_blue);
+ * END_CB;
+ *
+ * And later:
+ *
+ * CS_LOCALS;
+ * WRITE_CS_TABLE(cb, 3);
+ *
+ * Or using a little slower variant:
+ *
+ * CS_LOCALS;
+ * BEGIN_CS(cb, 3);
+ * OUT_CS_TABLE(cb, 3);
+ * END_CS;
+ */
+
+#ifndef R300_CB_H
+#define R300_CB_H
+
+#include "r300_reg.h"
+
+/* Yes, I know macros are ugly. However, they are much prettier than the code
+ * that they neatly hide away, and don't have the cost of function setup, so
+ * we're going to use them. */
+
+#ifdef DEBUG
+#define CB_DEBUG(x) x
+#else
+#define CB_DEBUG(x)
+#endif
+
+
+/**
+ * Command buffer setup.
+ */
+
+#define CB_LOCALS \
+ CB_DEBUG(int cs_count = 0;) \
+ uint32_t *cs_ptr = NULL; \
+ CB_DEBUG((void) cs_count;) (void) cs_ptr;
+
+#define NEW_CB(ptr, size) do { \
+ assert(sizeof(*ptr) == sizeof(uint32_t)); \
+ cs_ptr = (ptr) = (uint32_t*)malloc((size) * sizeof(uint32_t)); \
+ CB_DEBUG(cs_count = size;) \
+} while (0)
+
+#define BEGIN_CB(ptr, size) do { \
+ assert(sizeof(*ptr) == sizeof(uint32_t)); \
+ cs_ptr = ptr; \
+ CB_DEBUG(cs_count = size;) \
+} while (0)
+
+#define BEGIN_CS_AS_CB(r300, size) \
+ BEGIN_CB(r300->rws->get_cs_pointer(r300->rws, size), size)
+
+#define END_CB do { \
+ CB_DEBUG(if (cs_count != 0) \
+ debug_printf("r300: Warning: cs_count off by %d at (%s, %s:%i)\n", \
+ cs_count, __FUNCTION__, __FILE__, __LINE__);) \
+} while (0)
+
+
+/**
+ * Storing pure DWORDs.
+ */
+
+#define OUT_CB(value) do { \
+ *cs_ptr = (value); \
+ cs_ptr++; \
+ CB_DEBUG(cs_count--;) \
+} while (0)
+
+#define OUT_CB_TABLE(values, count) do { \
+ memcpy(cs_ptr, values, count * sizeof(uint32_t)); \
+ cs_ptr += count; \
+ CB_DEBUG(cs_count -= count;) \
+} while (0)
+
+#define OUT_CB_32F(value) \
+ OUT_CB(fui(value));
+
+#define OUT_CB_REG(register, value) do { \
+ assert(register); \
+ OUT_CB(CP_PACKET0(register, 0)); \
+ OUT_CB(value); \
+} while (0)
+
+/* Note: This expects count to be the number of registers,
+ * not the actual packet0 count! */
+#define OUT_CB_REG_SEQ(register, count) do { \
+ assert(register); \
+ OUT_CB(CP_PACKET0(register, (count) - 1)); \
+} while (0)
+
+#define OUT_CB_ONE_REG(register, count) do { \
+ assert(register); \
+ OUT_CB(CP_PACKET0(register, (count) - 1) | RADEON_ONE_REG_WR); \
+} while (0)
+
+#define OUT_CB_PKT3(op, count) \
+ OUT_CB(CP_PACKET3(op, count))
+
+#endif /* R300_CB_H */
diff --git a/src/gallium/drivers/r300/r300_chipset.c b/src/gallium/drivers/r300/r300_chipset.c
index e6dca66d4a..21f3b9d261 100644
--- a/src/gallium/drivers/r300/r300_chipset.c
+++ b/src/gallium/drivers/r300/r300_chipset.c
@@ -36,6 +36,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
caps->num_vert_fpus = 2;
caps->num_tex_units = 16;
caps->has_tcl = debug_get_bool_option("RADEON_NO_TCL", FALSE) ? FALSE : TRUE;
+ caps->has_hiz = TRUE;
caps->is_r400 = FALSE;
caps->is_r500 = FALSE;
caps->high_second_pipe = FALSE;
@@ -76,6 +77,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x4E54:
case 0x4E56:
caps->family = CHIP_FAMILY_RV350;
+ caps->has_hiz = FALSE;
caps->high_second_pipe = TRUE;
break;
@@ -106,6 +108,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x5B64:
case 0x5B65:
caps->family = CHIP_FAMILY_RV370;
+ caps->has_hiz = FALSE;
caps->high_second_pipe = TRUE;
break;
@@ -201,24 +204,28 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x5954:
case 0x5955:
caps->family = CHIP_FAMILY_RS480;
+ caps->has_hiz = FALSE;
caps->has_tcl = FALSE;
break;
case 0x5974:
case 0x5975:
caps->family = CHIP_FAMILY_RS482;
+ caps->has_hiz = FALSE;
caps->has_tcl = FALSE;
break;
case 0x5A41:
case 0x5A42:
caps->family = CHIP_FAMILY_RS400;
+ caps->has_hiz = FALSE;
caps->has_tcl = FALSE;
break;
case 0x5A61:
case 0x5A62:
caps->family = CHIP_FAMILY_RC410;
+ caps->has_hiz = FALSE;
caps->has_tcl = FALSE;
break;
diff --git a/src/gallium/drivers/r300/r300_chipset.h b/src/gallium/drivers/r300/r300_chipset.h
index ab649c3857..65750f54e7 100644
--- a/src/gallium/drivers/r300/r300_chipset.h
+++ b/src/gallium/drivers/r300/r300_chipset.h
@@ -42,6 +42,8 @@ struct r300_capabilities {
unsigned num_tex_units;
/* Whether or not TCL is physically present */
boolean has_tcl;
+ /* Some chipsets do not have HiZ RAM. */
+ boolean has_hiz;
/* Whether or not this is RV350 or newer, including all r400 and r500
* chipsets. The differences compared to the oldest r300 chips are:
* - Blend LTE/GTE thresholds
diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c
index 88ce186798..df2874d5bf 100644
--- a/src/gallium/drivers/r300/r300_context.c
+++ b/src/gallium/drivers/r300/r300_context.c
@@ -23,22 +23,64 @@
#include "draw/draw_context.h"
#include "util/u_memory.h"
+#include "util/u_sampler.h"
#include "util/u_simple_list.h"
#include "util/u_upload_mgr.h"
+#include "r300_cb.h"
#include "r300_context.h"
#include "r300_emit.h"
#include "r300_screen.h"
#include "r300_screen_buffer.h"
-#include "r300_state_invariant.h"
#include "r300_winsys.h"
#include <inttypes.h>
+static void r300_release_referenced_objects(struct r300_context *r300)
+{
+ struct pipe_framebuffer_state *fb =
+ (struct pipe_framebuffer_state*)r300->fb_state.state;
+ struct r300_textures_state *textures =
+ (struct r300_textures_state*)r300->textures_state.state;
+ struct r300_query *query, *temp;
+ unsigned i;
+
+ /* Framebuffer state. */
+ for (i = 0; i < fb->nr_cbufs; i++) {
+ pipe_surface_reference(&fb->cbufs[i], NULL);
+ }
+ pipe_surface_reference(&fb->zsbuf, NULL);
+
+ /* Textures. */
+ for (i = 0; i < textures->sampler_view_count; i++)
+ pipe_sampler_view_reference(
+ (struct pipe_sampler_view**)&textures->sampler_views[i], NULL);
+
+ /* The special dummy texture for texkill. */
+ if (r300->texkill_sampler) {
+ pipe_sampler_view_reference(
+ (struct pipe_sampler_view**)&r300->texkill_sampler,
+ NULL);
+ }
+
+ /* The SWTCL VBO. */
+ pipe_resource_reference(&r300->vbo, NULL);
+
+ /* Vertex buffers. */
+ for (i = 0; i < r300->vertex_buffer_count; i++) {
+ pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL);
+ }
+
+ /* If there are any queries pending or not destroyed, remove them now. */
+ foreach_s(query, temp, &r300->query_list) {
+ remove_from_list(query);
+ FREE(query);
+ }
+}
+
static void r300_destroy_context(struct pipe_context* context)
{
struct r300_context* r300 = r300_context(context);
- struct r300_query* query, * temp;
struct r300_atom *atom;
util_blitter_destroy(r300->blitter);
@@ -54,24 +96,24 @@ static void r300_destroy_context(struct pipe_context* context)
}
}
- /* Free the OQ BO. */
- context->screen->resource_destroy(context->screen, r300->oqbo);
-
- /* If there are any queries pending or not destroyed, remove them now. */
- foreach_s(query, temp, &r300->query_list) {
- remove_from_list(query);
- FREE(query);
- }
-
u_upload_destroy(r300->upload_vb);
u_upload_destroy(r300->upload_ib);
+ translate_cache_destroy(r300->tran.translate_cache);
+
+ r300_release_referenced_objects(r300);
+
+ FREE(r300->aa_state.state);
FREE(r300->blend_color_state.state);
FREE(r300->clip_state.state);
FREE(r300->fb_state.state);
+ FREE(r300->gpu_flush.state);
+ FREE(r300->hyperz_state.state);
+ FREE(r300->invariant_state.state);
FREE(r300->rs_block_state.state);
FREE(r300->scissor_state.state);
FREE(r300->textures_state.state);
+ FREE(r300->vap_invariant_state.state);
FREE(r300->viewport_state.state);
FREE(r300->ztop_state.state);
FREE(r300->fs_constants.state);
@@ -99,8 +141,10 @@ static void r300_flush_cb(void *data)
static void r300_setup_atoms(struct r300_context* r300)
{
+ boolean is_rv350 = r300->screen->caps.is_rv350;
boolean is_r500 = r300->screen->caps.is_r500;
boolean has_tcl = r300->screen->caps.has_tcl;
+ boolean drm_2_3_0 = r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0);
/* Create the actual atom list.
*
@@ -108,44 +152,75 @@ static void r300_setup_atoms(struct r300_context* r300)
* can affect performance and conformance if not handled with care.
*
* Some atoms never change size, others change every emit - those have
- * the size of 0 here. */
+ * the size of 0 here.
+ *
+ * NOTE: The framebuffer state is split into these atoms:
+ * - gpu_flush (unpipelined regs)
+ * - aa_state (unpipelined regs)
+ * - fb_state (unpipelined regs)
+ * - hyperz_state (unpipelined regs followed by pipelined ones)
+ * - fb_state_pipelined (pipelined regs)
+ * The motivation behind this is to be able to emit a strict
+ * subset of the regs, and to have reasonable register ordering. */
make_empty_list(&r300->atom_list);
- R300_INIT_ATOM(invariant_state, 71);
- R300_INIT_ATOM(query_start, 4);
+ /* SC, GB (unpipelined), RB3D (unpipelined), ZB (unpipelined). */
+ R300_INIT_ATOM(gpu_flush, 9);
+ R300_INIT_ATOM(aa_state, 4);
+ R300_INIT_ATOM(fb_state, 0);
+ /* ZB (unpipelined), SC. */
+ R300_INIT_ATOM(hyperz_state, 6);
R300_INIT_ATOM(ztop_state, 2);
+ /* ZB, FG. */
+ R300_INIT_ATOM(dsa_state, is_r500 ? 8 : 6);
+ /* RB3D. */
R300_INIT_ATOM(blend_state, 8);
R300_INIT_ATOM(blend_color_state, is_r500 ? 3 : 2);
- R300_INIT_ATOM(clip_state, has_tcl ? 5 + (6 * 4) : 2);
- R300_INIT_ATOM(dsa_state, is_r500 ? 8 : 6);
- R300_INIT_ATOM(fb_state, 0);
- R300_INIT_ATOM(rs_state, 0);
+ /* SC. */
R300_INIT_ATOM(scissor_state, 3);
+ /* GB, FG, GA, SU, SC, RB3D. */
+ R300_INIT_ATOM(invariant_state, 16 + (is_rv350 ? 4 : 0));
+ /* VAP. */
R300_INIT_ATOM(viewport_state, 9);
- R300_INIT_ATOM(rs_block_state, 0);
- R300_INIT_ATOM(vertex_stream_state, 0);
R300_INIT_ATOM(pvs_flush, 2);
+ R300_INIT_ATOM(vap_invariant_state, 9);
+ R300_INIT_ATOM(vertex_stream_state, 0);
R300_INIT_ATOM(vs_state, 0);
R300_INIT_ATOM(vs_constants, 0);
- R300_INIT_ATOM(texture_cache_inval, 2);
- R300_INIT_ATOM(textures_state, 0);
+ R300_INIT_ATOM(clip_state, has_tcl ? 5 + (6 * 4) : 2);
+ /* VAP, RS, GA, GB, SU, SC. */
+ R300_INIT_ATOM(rs_block_state, 0);
+ R300_INIT_ATOM(rs_state, 0);
+ /* SC, US. */
+ R300_INIT_ATOM(fb_state_pipelined, 5 + (drm_2_3_0 ? 3 : 0));
+ /* US. */
R300_INIT_ATOM(fs, 0);
R300_INIT_ATOM(fs_rc_constant_state, 0);
R300_INIT_ATOM(fs_constants, 0);
+ /* TX. */
+ R300_INIT_ATOM(texture_cache_inval, 2);
+ R300_INIT_ATOM(textures_state, 0);
+ /* ZB (unpipelined), SU. */
+ R300_INIT_ATOM(query_start, 4);
/* Replace emission functions for r500. */
- if (r300->screen->caps.is_r500) {
+ if (is_r500) {
r300->fs.emit = r500_emit_fs;
r300->fs_rc_constant_state.emit = r500_emit_fs_rc_constant_state;
r300->fs_constants.emit = r500_emit_fs_constants;
}
/* Some non-CSO atoms need explicit space to store the state locally. */
+ r300->aa_state.state = CALLOC_STRUCT(r300_aa_state);
r300->blend_color_state.state = CALLOC_STRUCT(r300_blend_color_state);
- r300->clip_state.state = CALLOC_STRUCT(pipe_clip_state);
+ r300->clip_state.state = CALLOC_STRUCT(r300_clip_state);
r300->fb_state.state = CALLOC_STRUCT(pipe_framebuffer_state);
+ r300->gpu_flush.state = CALLOC_STRUCT(pipe_framebuffer_state);
+ r300->hyperz_state.state = CALLOC_STRUCT(r300_hyperz_state);
+ r300->invariant_state.state = CALLOC_STRUCT(r300_invariant_state);
r300->rs_block_state.state = CALLOC_STRUCT(r300_rs_block);
r300->scissor_state.state = CALLOC_STRUCT(pipe_scissor_state);
r300->textures_state.state = CALLOC_STRUCT(r300_textures_state);
+ r300->vap_invariant_state.state = CALLOC_STRUCT(r300_vap_invariant_state);
r300->viewport_state.state = CALLOC_STRUCT(r300_viewport_state);
r300->ztop_state.state = CALLOC_STRUCT(r300_ztop_state);
r300->fs_constants.state = CALLOC_STRUCT(r300_constant_buffer);
@@ -155,11 +230,112 @@ static void r300_setup_atoms(struct r300_context* r300)
}
/* Some non-CSO atoms don't use the state pointer. */
- r300->invariant_state.allow_null_state = TRUE;
+ r300->fb_state_pipelined.allow_null_state = TRUE;
r300->fs_rc_constant_state.allow_null_state = TRUE;
r300->pvs_flush.allow_null_state = TRUE;
r300->query_start.allow_null_state = TRUE;
r300->texture_cache_inval.allow_null_state = TRUE;
+
+ /* Some states must be marked dirty here to properly set up
+ * hardware in the first command stream. */
+ r300->invariant_state.dirty = TRUE;
+ r300->pvs_flush.dirty = TRUE;
+ r300->vap_invariant_state.dirty = TRUE;
+ r300->texture_cache_inval.dirty = TRUE;
+ r300->textures_state.dirty = TRUE;
+}
+
+/* Not every state tracker calls every driver function before the first draw
+ * call and we must initialize the command buffers somehow. */
+static void r300_init_states(struct pipe_context *pipe)
+{
+ struct r300_context *r300 = r300_context(pipe);
+ struct pipe_blend_color bc = {{0}};
+ struct pipe_clip_state cs = {{{0}}};
+ struct pipe_scissor_state ss = {0};
+ struct r300_clip_state *clip =
+ (struct r300_clip_state*)r300->clip_state.state;
+ struct r300_gpu_flush *gpuflush =
+ (struct r300_gpu_flush*)r300->gpu_flush.state;
+ struct r300_vap_invariant_state *vap_invariant =
+ (struct r300_vap_invariant_state*)r300->vap_invariant_state.state;
+ struct r300_invariant_state *invariant =
+ (struct r300_invariant_state*)r300->invariant_state.state;
+ struct r300_hyperz_state *hyperz =
+ (struct r300_hyperz_state*)r300->hyperz_state.state;
+ CB_LOCALS;
+
+ pipe->set_blend_color(pipe, &bc);
+ pipe->set_scissor_state(pipe, &ss);
+
+ /* Initialize the clip state. */
+ if (r300_context(pipe)->screen->caps.has_tcl) {
+ pipe->set_clip_state(pipe, &cs);
+ } else {
+ BEGIN_CB(clip->cb, 2);
+ OUT_CB_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE);
+ END_CB;
+ }
+
+ /* Initialize the GPU flush. */
+ {
+ BEGIN_CB(gpuflush->cb_flush_clean, 6);
+
+ /* Flush and free renderbuffer caches. */
+ OUT_CB_REG(R300_RB3D_DSTCACHE_CTLSTAT,
+ R300_RB3D_DSTCACHE_CTLSTAT_DC_FREE_FREE_3D_TAGS |
+ R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D);
+ OUT_CB_REG(R300_ZB_ZCACHE_CTLSTAT,
+ R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE |
+ R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE);
+
+ /* Wait until the GPU is idle.
+ * This fixes random pixels sometimes appearing probably caused
+ * by incomplete rendering. */
+ OUT_CB_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN);
+ END_CB;
+ }
+
+ /* Initialize the VAP invariant state. */
+ {
+ BEGIN_CB(vap_invariant->cb, 9);
+ OUT_CB_REG(VAP_PVS_VTX_TIMEOUT_REG, 0xffff);
+ OUT_CB_REG_SEQ(R300_VAP_GB_VERT_CLIP_ADJ, 4);
+ OUT_CB_32F(1.0);
+ OUT_CB_32F(1.0);
+ OUT_CB_32F(1.0);
+ OUT_CB_32F(1.0);
+ OUT_CB_REG(R300_VAP_PSC_SGN_NORM_CNTL, R300_SGN_NORM_NO_ZERO);
+ END_CB;
+ }
+
+ /* Initialize the invariant state. */
+ {
+ BEGIN_CB(invariant->cb, r300->invariant_state.size);
+ OUT_CB_REG(R300_GB_SELECT, 0);
+ OUT_CB_REG(R300_FG_FOG_BLEND, 0);
+ OUT_CB_REG(R300_GA_ROUND_MODE, 1);
+ OUT_CB_REG(R300_GA_OFFSET, 0);
+ OUT_CB_REG(R300_SU_TEX_WRAP, 0);
+ OUT_CB_REG(R300_SU_DEPTH_SCALE, 0x4B7FFFFF);
+ OUT_CB_REG(R300_SU_DEPTH_OFFSET, 0);
+ OUT_CB_REG(R300_SC_EDGERULE, 0x2DA49525);
+
+ if (r300->screen->caps.is_rv350) {
+ OUT_CB_REG(R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD, 0x01010101);
+ OUT_CB_REG(R500_RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD, 0xFEFEFEFE);
+ }
+ END_CB;
+ }
+
+ /* Initialize the hyperz state. */
+ {
+ BEGIN_CB(&hyperz->cb_begin, 6);
+ OUT_CB_REG(R300_ZB_BW_CNTL, 0);
+ OUT_CB_REG(R300_ZB_DEPTHCLEARVALUE, 0);
+ OUT_CB_REG(R300_SC_HYPERZ, 0x1C);
+ END_CB;
+ }
}
struct pipe_context* r300_create_context(struct pipe_screen* screen,
@@ -195,9 +371,6 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
r300_setup_atoms(r300);
- /* Open up the OQ BO. */
- r300->oqbo = pipe_buffer_create(screen,
- R300_BIND_OQBO, 4096);
make_empty_list(&r300->query_list);
r300_init_blit_functions(r300);
@@ -207,8 +380,6 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
r300_init_state_functions(r300);
r300_init_resource_functions(r300);
- r300->invariant_state.dirty = TRUE;
-
rws->set_flush_cb(r300->rws, r300_flush_cb, r300);
r300->dirty_hw++;
@@ -227,6 +398,34 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
if (r300->upload_vb == NULL)
goto no_upload_vb;
+ r300->tran.translate_cache = translate_cache_create();
+
+ r300_init_states(&r300->context);
+
+ /* The KIL opcode needs the first texture unit to be enabled
+ * on r3xx-r4xx. In order to calm down the CS checker, we bind this
+ * dummy texture there. */
+ if (!r300->screen->caps.is_r500) {
+ struct pipe_resource *tex;
+ struct pipe_resource rtempl = {{0}};
+ struct pipe_sampler_view vtempl = {{0}};
+
+ rtempl.target = PIPE_TEXTURE_2D;
+ rtempl.format = PIPE_FORMAT_I8_UNORM;
+ rtempl.bind = PIPE_BIND_SAMPLER_VIEW;
+ rtempl.width0 = 1;
+ rtempl.height0 = 1;
+ rtempl.depth0 = 1;
+ tex = screen->resource_create(screen, &rtempl);
+
+ u_sampler_view_default_template(&vtempl, tex, tex->format);
+
+ r300->texkill_sampler = (struct r300_sampler_view*)
+ r300->context.create_sampler_view(&r300->context, tex, &vtempl);
+
+ pipe_resource_reference(&tex, NULL);
+ }
+
return &r300->context;
no_upload_ib:
@@ -238,10 +437,7 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
boolean r300_check_cs(struct r300_context *r300, unsigned size)
{
- struct r300_cs_info cs_info;
-
- r300->rws->get_cs_info(r300->rws, &cs_info);
- return size <= cs_info.free;
+ return size <= r300->rws->get_cs_free_dwords(r300->rws);
}
void r300_finish(struct r300_context *r300)
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index 48ec52d26c..50dcd0fc67 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -31,6 +31,8 @@
#include "util/u_inlines.h"
#include "util/u_transfer.h"
+#include "translate/translate_cache.h"
+
#include "r300_defines.h"
#include "r300_screen.h"
@@ -59,68 +61,83 @@ struct r300_atom {
boolean allow_null_state;
};
+struct r300_aa_state {
+ struct r300_surface *dest;
+
+ uint32_t aa_config;
+ uint32_t aaresolve_ctl;
+};
+
struct r300_blend_state {
- uint32_t blend_control; /* R300_RB3D_CBLEND: 0x4e04 */
- uint32_t alpha_blend_control; /* R300_RB3D_ABLEND: 0x4e08 */
- uint32_t color_channel_mask; /* R300_RB3D_COLOR_CHANNEL_MASK: 0x4e0c */
- uint32_t rop; /* R300_RB3D_ROPCNTL: 0x4e18 */
- uint32_t dither; /* R300_RB3D_DITHER_CTL: 0x4e50 */
+ uint32_t cb[8];
+ uint32_t cb_no_readwrite[8];
};
struct r300_blend_color_state {
- /* RV515 and earlier */
- uint32_t blend_color; /* R300_RB3D_BLEND_COLOR: 0x4e10 */
- /* R520 and newer */
- uint32_t blend_color_red_alpha; /* R500_RB3D_CONSTANT_COLOR_AR: 0x4ef8 */
- uint32_t blend_color_green_blue; /* R500_RB3D_CONSTANT_COLOR_GB: 0x4efc */
+ uint32_t cb[3];
+};
+
+struct r300_clip_state {
+ struct pipe_clip_state clip;
+
+ uint32_t cb[29];
};
struct r300_dsa_state {
+ struct pipe_depth_stencil_alpha_state dsa;
+
+ /* This is actually a command buffer with named dwords. */
+ uint32_t cb_begin;
uint32_t alpha_function; /* R300_FG_ALPHA_FUNC: 0x4bd4 */
- uint32_t alpha_reference; /* R500_FG_ALPHA_VALUE: 0x4be0 */
+ uint32_t cb_reg_seq;
uint32_t z_buffer_control; /* R300_ZB_CNTL: 0x4f00 */
uint32_t z_stencil_control; /* R300_ZB_ZSTENCILCNTL: 0x4f04 */
uint32_t stencil_ref_mask; /* R300_ZB_STENCILREFMASK: 0x4f08 */
+ uint32_t cb_reg;
uint32_t stencil_ref_bf; /* R500_ZB_STENCILREFMASK_BF: 0x4fd4 */
+ /* The second command buffer disables zbuffer reads and writes. */
+ uint32_t cb_no_readwrite[8];
+
/* Whether a two-sided stencil is enabled. */
boolean two_sided;
/* Whether a fallback should be used for a two-sided stencil ref value. */
boolean two_sided_stencil_ref;
};
+struct r300_hyperz_state {
+ /* This is actually a command buffer with named dwords. */
+ uint32_t cb_begin;
+ uint32_t zb_bw_cntl; /* R300_ZB_BW_CNTL */
+ uint32_t cb_reg1;
+ uint32_t zb_depthclearvalue; /* R300_ZB_DEPTHCLEARVALUE */
+ uint32_t cb_reg2;
+ uint32_t sc_hyperz; /* R300_SC_HYPERZ */
+};
+
+struct r300_gpu_flush {
+ uint32_t cb_flush_clean[6];
+};
+
struct r300_rs_state {
/* Original rasterizer state. */
struct pipe_rasterizer_state rs;
/* Draw-specific rasterizer state. */
struct pipe_rasterizer_state rs_draw;
- uint32_t vap_control_status; /* R300_VAP_CNTL_STATUS: 0x2140 */
- uint32_t antialiasing_config; /* R300_GB_AA_CONFIG: 0x4020 */
- uint32_t point_size; /* R300_GA_POINT_SIZE: 0x421c */
- uint32_t point_minmax; /* R300_GA_POINT_MINMAX: 0x4230 */
- uint32_t line_control; /* R300_GA_LINE_CNTL: 0x4234 */
- float depth_scale; /* R300_SU_POLY_OFFSET_FRONT_SCALE: 0x42a4 */
- /* R300_SU_POLY_OFFSET_BACK_SCALE: 0x42ac */
- float depth_offset; /* R300_SU_POLY_OFFSET_FRONT_OFFSET: 0x42a8 */
- /* R300_SU_POLY_OFFSET_BACK_OFFSET: 0x42b0 */
- uint32_t polygon_offset_enable; /* R300_SU_POLY_OFFSET_ENABLE: 0x42b4 */
- uint32_t cull_mode; /* R300_SU_CULL_MODE: 0x42b8 */
- uint32_t line_stipple_config; /* R300_GA_LINE_STIPPLE_CONFIG: 0x4328 */
- uint32_t line_stipple_value; /* R300_GA_LINE_STIPPLE_VALUE: 0x4260 */
+ /* Command buffers. */
+ uint32_t cb_main[25];
+ uint32_t cb_poly_offset_zb16[5];
+ uint32_t cb_poly_offset_zb24[5];
+
+ /* The index to cb_main where the cull_mode register value resides. */
+ unsigned cull_mode_index;
+
+ /* Whether polygon offset is enabled. */
+ boolean polygon_offset_enable;
+
+ /* This is emitted in the draw function. */
uint32_t color_control; /* R300_GA_COLOR_CONTROL: 0x4278 */
- uint32_t polygon_mode; /* R300_GA_POLY_MODE: 0x4288 */
- uint32_t clip_rule; /* R300_SC_CLIP_RULE: 0x43D0 */
-
- /* Specifies top of Raster pipe specific enable controls,
- * i.e. texture coordinates stuffing for points, lines, triangles */
- uint32_t stuffing_enable; /* R300_GB_ENABLE: 0x4008 */
-
- /* Point sprites texture coordinates, 0: lower left, 1: upper right */
- float point_texcoord_left; /* R300_GA_POINT_S0: 0x4200 */
- float point_texcoord_bottom; /* R300_GA_POINT_T0: 0x4204 */
- float point_texcoord_right; /* R300_GA_POINT_S1: 0x4208 */
- float point_texcoord_top; /* R300_GA_POINT_T1: 0x420c */
};
struct r300_rs_block {
@@ -163,16 +180,14 @@ struct r300_sampler_view {
/* Copy of r300_texture::texture_format_state with format-specific bits
* added. */
struct r300_texture_format_state format;
+
+ /* The texture cache region for this texture. */
+ uint32_t texcache_region;
};
struct r300_texture_fb_state {
- /* Colorbuffer. */
- uint32_t colorpitch[R300_MAX_TEXTURE_LEVELS]; /* R300_RB3D_COLORPITCH[0-3]*/
- uint32_t us_out_fmt; /* R300_US_OUT_FMT[0-3] */
-
- /* Zbuffer. */
- uint32_t depthpitch[R300_MAX_TEXTURE_LEVELS]; /* R300_RB3D_DEPTHPITCH */
- uint32_t zb_format; /* R300_ZB_FORMAT */
+ uint32_t pitch[R300_MAX_TEXTURE_LEVELS]; /* COLORPITCH or DEPTHPITCH. */
+ uint32_t format; /* US_OUT_FMT or R300_ZB_FORMAT */
};
struct r300_texture_sampler_state {
@@ -205,6 +220,14 @@ struct r300_vertex_stream_state {
unsigned count;
};
+struct r300_invariant_state {
+ uint32_t cb[20];
+};
+
+struct r300_vap_invariant_state {
+ uint32_t cb[9];
+};
+
struct r300_viewport_state {
float xscale; /* R300_VAP_VPORT_XSCALE: 0x2098 */
float xoffset; /* R300_VAP_VPORT_XOFFSET: 0x209c */
@@ -224,7 +247,7 @@ struct r300_ztop_state {
struct r300_constant_buffer {
/* Buffer of constants */
- float constants[256][4];
+ uint32_t constants[256][4];
/* Total number of constants */
unsigned count;
};
@@ -239,14 +262,23 @@ struct r300_constant_buffer {
struct r300_query {
/* The kind of query. Currently only OQ is supported. */
unsigned type;
- /* The current count of this query. Required to be at least 32 bits. */
- unsigned int count;
- /* The offset of this query into the query buffer, in bytes. */
- unsigned offset;
+ /* The number of pipes where query results are stored. */
+ unsigned num_pipes;
+ /* How many results have been written, in dwords. It's incremented
+ * after end_query and flush. */
+ unsigned num_results;
/* if we've flushed the query */
boolean flushed;
/* if begin has been emitted */
boolean begin_emitted;
+
+ /* The buffer where query results are stored. */
+ struct r300_winsys_buffer *buffer;
+ /* The size of the buffer. */
+ unsigned buffer_size;
+ /* The domain of the buffer. */
+ enum r300_buffer_domain domain;
+
/* Linked list members. */
struct r300_query* prev;
struct r300_query* next;
@@ -268,6 +300,19 @@ struct r300_fence {
boolean signalled;
};
+struct r300_surface {
+ struct pipe_surface base;
+
+ /* Winsys buffer backing the texture. */
+ struct r300_winsys_buffer *buffer;
+
+ enum r300_buffer_domain domain;
+
+ uint32_t offset;
+ uint32_t pitch; /* COLORPITCH or DEPTHPITCH. */
+ uint32_t format; /* US_OUT_FMT or R300_ZB_FORMAT. */
+};
+
struct r300_texture {
/* Parent class */
struct u_resource b;
@@ -326,9 +371,34 @@ struct r300_vertex_element_state {
unsigned count;
struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS];
+ /* If (velem[i].src_format != hw_format[i]), the vertex buffer
+ * referenced by this vertex element cannot be used for rendering and
+ * its vertex data must be translated to hw_format[i]. */
+ enum pipe_format hw_format[PIPE_MAX_ATTRIBS];
+ unsigned hw_format_size[PIPE_MAX_ATTRIBS];
+
+ /* The size of the vertex, in dwords. */
+ unsigned vertex_size_dwords;
+
+ /* This might mean two things:
+ * - src_format != hw_format, as discussed above.
+ * - src_offset % 4 != 0. */
+ boolean incompatible_layout;
+
struct r300_vertex_stream_state vertex_stream;
};
+struct r300_translate_context {
+ /* Translate cache for incompatible vertex offset/stride/format fallback. */
+ struct translate_cache *translate_cache;
+
+ /* The vertex buffer slot containing the translated buffer. */
+ unsigned vb_slot;
+
+ /* Saved and new vertex element state. */
+ void *saved_velems, *new_velems;
+};
+
struct r300_context {
/* Parent class */
struct pipe_context context;
@@ -343,21 +413,30 @@ struct r300_context {
struct blitter_context* blitter;
/* Stencil two-sided reference value fallback. */
struct r300_stencilref_context *stencilref_fallback;
+ /* For translating vertex buffers having incompatible vertex layout. */
+ struct r300_translate_context tran;
/* Vertex buffer for rendering. */
struct pipe_resource* vbo;
+ /* The KIL opcode needs the first texture unit to be enabled
+ * on r3xx-r4xx. In order to calm down the CS checker, we bind this
+ * dummy texture there. */
+ struct r300_sampler_view *texkill_sampler;
/* Offset into the VBO. */
size_t vbo_offset;
- /* Occlusion query buffer. */
- struct pipe_resource* oqbo;
- /* Query list. */
+ /* The currently active query. */
struct r300_query *query_current;
+ /* The saved query for blitter operations. */
+ struct r300_query *blitter_saved_query;
+ /* Query list. */
struct r300_query query_list;
/* Various CSO state objects. */
/* Beginning of atom list. */
struct r300_atom atom_list;
+ /* Anti-aliasing (MSAA) state. */
+ struct r300_atom aa_state;
/* Blend state. */
struct r300_atom blend_state;
/* Blend color state. */
@@ -374,6 +453,10 @@ struct r300_context {
struct r300_atom fs_constants;
/* Framebuffer state. */
struct r300_atom fb_state;
+ /* Framebuffer state (pipelined regs). */
+ struct r300_atom fb_state_pipelined;
+ /* HyperZ state (various SC/ZB bits). */
+ struct r300_atom hyperz_state;
/* Occlusion query. */
struct r300_atom query_start;
/* Rasterizer state. */
@@ -396,8 +479,12 @@ struct r300_context {
struct r300_atom ztop_state;
/* PVS flush. */
struct r300_atom pvs_flush;
+ /* VAP invariant state. */
+ struct r300_atom vap_invariant_state;
/* Texture cache invalidate. */
struct r300_atom texture_cache_inval;
+ /* GPU flush. */
+ struct r300_atom gpu_flush;
/* Invariant state. This must be emitted to get the engine started. */
struct r300_atom invariant_state;
@@ -414,9 +501,6 @@ struct r300_context {
struct vertex_info vertex_info;
struct pipe_stencil_ref stencil_ref;
-
- struct pipe_clip_state clip;
-
struct pipe_viewport_state viewport;
/* Stream locations for SWTCL. */
@@ -434,6 +518,8 @@ struct r300_context {
int sprite_coord_enable;
/* Whether two-sided color selection is enabled (AKA light_twoside). */
boolean two_sided_color;
+ /* Incompatible vertex buffer layout? (misaligned stride or buffer_offset) */
+ boolean incompatible_vb_layout;
/* upload managers */
struct u_upload_mgr *upload_vb;
@@ -449,6 +535,11 @@ static INLINE struct r300_query* r300_query(struct pipe_query* q)
return (struct r300_query*)q;
}
+static INLINE struct r300_surface* r300_surface(struct pipe_surface* surf)
+{
+ return (struct r300_surface*)surf;
+}
+
static INLINE struct r300_texture* r300_texture(struct pipe_resource* tex)
{
return (struct r300_texture*)tex;
@@ -467,6 +558,9 @@ static INLINE struct r300_fragment_shader *r300_fs(struct r300_context *r300)
struct pipe_context* r300_create_context(struct pipe_screen* screen,
void *priv);
+boolean r300_check_cs(struct r300_context *r300, unsigned size);
+void r300_finish(struct r300_context *r300);
+
/* Context initialization. */
struct draw_stage* r300_draw_stage(struct r300_context* r300);
void r300_init_blit_functions(struct r300_context *r300);
@@ -476,10 +570,29 @@ void r300_init_render_functions(struct r300_context *r300);
void r300_init_state_functions(struct r300_context* r300);
void r300_init_resource_functions(struct r300_context* r300);
-boolean r300_check_cs(struct r300_context *r300, unsigned size);
-void r300_finish(struct r300_context *r300);
+/* r300_query.c */
+void r300_resume_query(struct r300_context *r300,
+ struct r300_query *query);
+void r300_stop_query(struct r300_context *r300);
+
+/* r300_render_translate.c */
+void r300_begin_vertex_translate(struct r300_context *r300);
+void r300_end_vertex_translate(struct r300_context *r300);
+void r300_translate_index_buffer(struct r300_context *r300,
+ struct pipe_resource **index_buffer,
+ unsigned *index_size, unsigned index_offset,
+ unsigned *start, unsigned count);
+
+/* r300_render_stencilref.c */
+void r300_plug_in_stencil_ref_fallback(struct r300_context *r300);
+
+/* r300_state.c */
+void r300_mark_fs_code_dirty(struct r300_context *r300);
+
+/* r300_debug.c */
void r500_dump_rs_block(struct r300_rs_block *rs);
+
static INLINE boolean CTX_DBG_ON(struct r300_context * ctx, unsigned flags)
{
return SCREEN_DBG_ON(ctx->screen, flags);
diff --git a/src/gallium/drivers/r300/r300_cs.h b/src/gallium/drivers/r300/r300_cs.h
index 9c8c273902..1db7da642b 100644
--- a/src/gallium/drivers/r300/r300_cs.h
+++ b/src/gallium/drivers/r300/r300_cs.h
@@ -20,171 +20,133 @@
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**
+ * This file contains macros for immediate command submission.
+ */
+
#ifndef R300_CS_H
#define R300_CS_H
-#include "util/u_math.h"
-
#include "r300_reg.h"
+#include "r300_context.h"
#include "r300_winsys.h"
/* Yes, I know macros are ugly. However, they are much prettier than the code
* that they neatly hide away, and don't have the cost of function setup,so
* we're going to use them. */
-#define MAX_CS_SIZE 64 * 1024 / 4
-
-#define VERY_VERBOSE_CS 1
-#define VERY_VERBOSE_REGISTERS 1
+#ifdef DEBUG
+#define CS_DEBUG(x) x
+#else
+#define CS_DEBUG(x)
+#endif
-/* XXX stolen from radeon_reg.h */
-#define RADEON_CP_PACKET0 0x0
-
-#define CP_PACKET0(register, count) \
- (RADEON_CP_PACKET0 | ((count) << 16) | ((register) >> 2))
+/**
+ * Command submission setup.
+ */
#define CS_LOCALS(context) \
struct r300_context* const cs_context_copy = (context); \
struct r300_winsys_screen *cs_winsys = cs_context_copy->rws; \
- int cs_count = 0; (void) cs_count;
-
-#define CHECK_CS(size) \
- assert(r300_check_cs(cs_context_copy, (size)))
+ CS_DEBUG(int cs_count = 0; (void) cs_count;)
#define BEGIN_CS(size) do { \
- CHECK_CS(size); \
- if (VERY_VERBOSE_CS) { \
- DBG(cs_context_copy, DBG_CS, "r300: BEGIN_CS, count %d, in %s (%s:%d)\n", \
- size, __FUNCTION__, __FILE__, __LINE__); \
- } \
- cs_winsys->begin_cs(cs_winsys, (size), \
- __FILE__, __FUNCTION__, __LINE__); \
- cs_count = size; \
+ assert(r300_check_cs(cs_context_copy, (size))); \
+ CS_DEBUG(cs_count = size;) \
+} while (0)
+
+#ifdef DEBUG
+#define END_CS do { \
+ if (cs_count != 0) \
+ debug_printf("r300: Warning: cs_count off by %d at (%s, %s:%i)\n", \
+ cs_count, __FUNCTION__, __FILE__, __LINE__); \
+ cs_count = 0; \
} while (0)
+#else
+#define END_CS
+#endif
+
+/**
+ * Writing pure DWORDs.
+ */
#define OUT_CS(value) do { \
- if (VERY_VERBOSE_CS || VERY_VERBOSE_REGISTERS) { \
- DBG(cs_context_copy, DBG_CS, "r300: writing %08x\n", value); \
- } \
cs_winsys->write_cs_dword(cs_winsys, (value)); \
- cs_count--; \
+ CS_DEBUG(cs_count--;) \
} while (0)
#define OUT_CS_32F(value) do { \
- if (VERY_VERBOSE_CS || VERY_VERBOSE_REGISTERS) { \
- DBG(cs_context_copy, DBG_CS, "r300: writing %f\n", value); \
- } \
cs_winsys->write_cs_dword(cs_winsys, fui(value)); \
- cs_count--; \
+ CS_DEBUG(cs_count--;) \
} while (0)
#define OUT_CS_REG(register, value) do { \
- if (VERY_VERBOSE_REGISTERS) \
- DBG(cs_context_copy, DBG_CS, "r300: writing 0x%08X to register 0x%04X\n", \
- value, register); \
assert(register); \
cs_winsys->write_cs_dword(cs_winsys, CP_PACKET0(register, 0)); \
cs_winsys->write_cs_dword(cs_winsys, value); \
- cs_count -= 2; \
+ CS_DEBUG(cs_count -= 2;) \
} while (0)
/* Note: This expects count to be the number of registers,
* not the actual packet0 count! */
#define OUT_CS_REG_SEQ(register, count) do { \
- if (VERY_VERBOSE_REGISTERS) \
- DBG(cs_context_copy, DBG_CS, "r300: writing register sequence of %d to 0x%04X\n", \
- count, register); \
assert(register); \
cs_winsys->write_cs_dword(cs_winsys, CP_PACKET0((register), ((count) - 1))); \
- cs_count--; \
+ CS_DEBUG(cs_count--;) \
} while (0)
#define OUT_CS_TABLE(values, count) do { \
- if (VERY_VERBOSE_REGISTERS) \
- DBG(cs_context_copy, DBG_CS, "r300: writing table of %d dwords\n", count); \
cs_winsys->write_cs_table(cs_winsys, values, count); \
- cs_count -= count; \
+ CS_DEBUG(cs_count -= count;) \
} while (0)
-#define OUT_CS_BUF_RELOC(bo, offset, rd, wd, flags) do { \
- DBG(cs_context_copy, DBG_CS, "r300: writing relocation for buffer %p, offset %d, " \
- "domains (%d, %d, %d)\n", \
- bo, offset, rd, wd, flags); \
- assert(bo); \
- cs_winsys->write_cs_dword(cs_winsys, offset); \
- r300_buffer_write_reloc(cs_winsys, r300_buffer(bo), rd, wd, flags); \
- cs_count -= 3; \
+#define OUT_CS_ONE_REG(register, count) do { \
+ assert(register); \
+ cs_winsys->write_cs_dword(cs_winsys, CP_PACKET0((register), ((count) - 1)) | RADEON_ONE_REG_WR); \
+ CS_DEBUG(cs_count--;) \
} while (0)
-
-#define OUT_CS_TEX_RELOC(tex, offset, rd, wd, flags) do { \
- DBG(cs_context_copy, DBG_CS, "r300: writing relocation for texture %p, offset %d, " \
- "domains (%d, %d, %d)\n", \
- tex, offset, rd, wd, flags); \
- assert(tex); \
- cs_winsys->write_cs_dword(cs_winsys, offset); \
- r300_texture_write_reloc(cs_winsys, tex, rd, wd, flags); \
- cs_count -= 3; \
+#define OUT_CS_PKT3(op, count) do { \
+ cs_winsys->write_cs_dword(cs_winsys, CP_PACKET3(op, count)); \
+ CS_DEBUG(cs_count--;) \
} while (0)
-#define OUT_CS_BUF_RELOC_NO_OFFSET(bo, rd, wd, flags) do { \
- DBG(cs_context_copy, DBG_CS, "r300: writing relocation for buffer %p, " \
- "domains (%d, %d, %d)\n", \
- bo, rd, wd, flags); \
+/**
+ * Writing relocations.
+ */
+
+#define OUT_CS_RELOC(bo, offset, rd, wd, flags) do { \
assert(bo); \
- r300_buffer_write_reloc(cs_winsys, r300_buffer(bo), rd, wd, flags); \
- cs_count -= 2; \
+ cs_winsys->write_cs_dword(cs_winsys, offset); \
+ cs_winsys->write_cs_reloc(cs_winsys, bo, rd, wd, flags); \
+ CS_DEBUG(cs_count -= 3;) \
} while (0)
-#define END_CS do { \
- if (VERY_VERBOSE_CS) { \
- DBG(cs_context_copy, DBG_CS, "r300: END_CS in %s (%s:%d)\n", __FUNCTION__, \
- __FILE__, __LINE__); \
- } \
- if (cs_count != 0) \
- debug_printf("r300: Warning: cs_count off by %d\n", cs_count); \
- cs_winsys->end_cs(cs_winsys, __FILE__, __FUNCTION__, __LINE__); \
+#define OUT_CS_BUF_RELOC(bo, offset, rd, wd, flags) do { \
+ assert(bo); \
+ OUT_CS_RELOC(r300_buffer(bo)->buf, offset, rd, wd, flags); \
} while (0)
-#define FLUSH_CS do { \
- if (VERY_VERBOSE_CS) { \
- DBG(cs_context_copy, DBG_CS, "r300: FLUSH_CS in %s (%s:%d)\n\n", __FUNCTION__, \
- __FILE__, __LINE__); \
- } \
- if (SCREEN_DBG_ON(r300->screen, DBG_STATS)) { \
- r300->flush_counter++; \
- } \
- cs_winsys->flush_cs(cs_winsys); \
+#define OUT_CS_TEX_RELOC(tex, offset, rd, wd, flags) do { \
+ assert(tex); \
+ OUT_CS_RELOC(tex->buffer, offset, rd, wd, flags); \
} while (0)
-#define RADEON_ONE_REG_WR (1 << 15)
-
-#define OUT_CS_ONE_REG(register, count) do { \
- if (VERY_VERBOSE_REGISTERS) \
- DBG(cs_context_copy, DBG_CS, "r300: writing data sequence of %d to 0x%04X\n", \
- count, register); \
- assert(register); \
- cs_winsys->write_cs_dword(cs_winsys, CP_PACKET0((register), ((count) - 1)) | RADEON_ONE_REG_WR); \
- cs_count--; \
+#define OUT_CS_BUF_RELOC_NO_OFFSET(bo, rd, wd, flags) do { \
+ assert(bo); \
+ cs_winsys->write_cs_reloc(cs_winsys, r300_buffer(bo)->buf, rd, wd, flags); \
+ CS_DEBUG(cs_count -= 2;) \
} while (0)
-#define CP_PACKET3(op, count) \
- (RADEON_CP_PACKET3 | (op) | ((count) << 16))
-#define OUT_CS_PKT3(op, count) do { \
- cs_winsys->write_cs_dword(cs_winsys, CP_PACKET3(op, count)); \
- cs_count--; \
-} while (0)
+/**
+ * Command buffer emission.
+ */
-#define OUT_CS_INDEX_RELOC(bo, offset, count, rd, wd, flags) do { \
- DBG(cs_context_copy, DBG_CS, "r300: writing relocation for index buffer %p," \
- "offset %d\n", bo, offset); \
- assert(bo); \
- cs_winsys->write_cs_dword(cs_winsys, offset); \
- cs_winsys->write_cs_dword(cs_winsys, count); \
- cs_winsys->write_cs_reloc(cs_winsys, bo, rd, wd, flags); \
- cs_count -= 4; \
+#define WRITE_CS_TABLE(values, count) do { \
+ CS_DEBUG(assert(cs_count == 0);) \
+ cs_winsys->write_cs_table(cs_winsys, values, count); \
} while (0)
#endif /* R300_CS_H */
diff --git a/src/gallium/drivers/r300/r300_debug.c b/src/gallium/drivers/r300/r300_debug.c
index 297791f3ff..a6cd86e392 100644
--- a/src/gallium/drivers/r300/r300_debug.c
+++ b/src/gallium/drivers/r300/r300_debug.c
@@ -29,7 +29,6 @@
static const struct debug_named_value debug_options[] = {
{ "fp", DBG_FP, "Fragment program handling (for debugging)" },
{ "vp", DBG_VP, "Vertex program handling (for debugging)" },
- { "cs", DBG_CS, "Command submissions (for debugging)" },
{ "draw", DBG_DRAW, "Draw and emit (for debugging)" },
{ "tex", DBG_TEX, "Textures (for debugging)" },
{ "texalloc", DBG_TEXALLOC, "Texture allocation (for debugging)" },
@@ -39,6 +38,7 @@ static const struct debug_named_value debug_options[] = {
{ "anisohq", DBG_ANISOHQ, "High quality anisotropic filtering (for benchmarking)" },
{ "notiling", DBG_NO_TILING, "Disable tiling (for benchmarking)" },
{ "noimmd", DBG_NO_IMMD, "Disable immediate mode (for benchmarking)" },
+ { "fakeocc", DBG_FAKE_OCC, "Use fake occlusion queries (for lulz)" },
{ "stats", DBG_STATS, "Gather statistics (for lulz)" },
/* must be last */
diff --git a/src/gallium/drivers/r300/r300_defines.h b/src/gallium/drivers/r300/r300_defines.h
index 83c9ec7e39..d510d80a7b 100644
--- a/src/gallium/drivers/r300/r300_defines.h
+++ b/src/gallium/drivers/r300/r300_defines.h
@@ -30,13 +30,7 @@
#define R300_RESOURCE_FLAG_TRANSFER PIPE_RESOURCE_FLAG_DRV_PRIV
-#define R300_INVALID_FORMAT (~0)
-
-/* XXX: this is just a bandaid on larger problems in
- * r300_screen_buffer.h which doesn't seem to be fully ported to
- * gallium-resources.
- */
-#define R300_BIND_OQBO (1<<21)
+#define R300_INVALID_FORMAT 0xffff
/* Tiling flags. */
enum r300_buffer_tiling {
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index c329c0f30f..014b382edf 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -43,21 +43,11 @@ void r300_emit_blend_state(struct r300_context* r300,
(struct pipe_framebuffer_state*)r300->fb_state.state;
CS_LOCALS(r300);
- BEGIN_CS(size);
- OUT_CS_REG(R300_RB3D_ROPCNTL, blend->rop);
- OUT_CS_REG_SEQ(R300_RB3D_CBLEND, 3);
if (fb->nr_cbufs) {
- OUT_CS(blend->blend_control);
- OUT_CS(blend->alpha_blend_control);
- OUT_CS(blend->color_channel_mask);
+ WRITE_CS_TABLE(blend->cb, size);
} else {
- OUT_CS(0);
- OUT_CS(0);
- OUT_CS(0);
- /* XXX also disable fastfill here once it's supported */
+ WRITE_CS_TABLE(blend->cb_no_readwrite, size);
}
- OUT_CS_REG(R300_RB3D_DITHER_CTL, blend->dither);
- END_CS;
}
void r300_emit_blend_color_state(struct r300_context* r300,
@@ -66,40 +56,16 @@ void r300_emit_blend_color_state(struct r300_context* r300,
struct r300_blend_color_state* bc = (struct r300_blend_color_state*)state;
CS_LOCALS(r300);
- if (r300->screen->caps.is_r500) {
- BEGIN_CS(size);
- OUT_CS_REG_SEQ(R500_RB3D_CONSTANT_COLOR_AR, 2);
- OUT_CS(bc->blend_color_red_alpha);
- OUT_CS(bc->blend_color_green_blue);
- END_CS;
- } else {
- BEGIN_CS(size);
- OUT_CS_REG(R300_RB3D_BLEND_COLOR, bc->blend_color);
- END_CS;
- }
+ WRITE_CS_TABLE(bc->cb, size);
}
void r300_emit_clip_state(struct r300_context* r300,
unsigned size, void* state)
{
- struct pipe_clip_state* clip = (struct pipe_clip_state*)state;
+ struct r300_clip_state* clip = (struct r300_clip_state*)state;
CS_LOCALS(r300);
- if (r300->screen->caps.has_tcl) {
- BEGIN_CS(size);
- OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG,
- (r300->screen->caps.is_r500 ?
- R500_PVS_UCP_START : R300_PVS_UCP_START));
- OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, 6 * 4);
- OUT_CS_TABLE(clip->ucp, 6 * 4);
- OUT_CS_REG(R300_VAP_CLIP_CNTL, ((1 << clip->nr) - 1) |
- R300_PS_UCP_MODE_CLIP_AS_TRIFAN);
- END_CS;
- } else {
- BEGIN_CS(size);
- OUT_CS_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE);
- END_CS;
- }
+ WRITE_CS_TABLE(clip->cb, size);
}
void r300_emit_dsa_state(struct r300_context* r300, unsigned size, void* state)
@@ -107,27 +73,13 @@ void r300_emit_dsa_state(struct r300_context* r300, unsigned size, void* state)
struct r300_dsa_state* dsa = (struct r300_dsa_state*)state;
struct pipe_framebuffer_state* fb =
(struct pipe_framebuffer_state*)r300->fb_state.state;
- struct pipe_stencil_ref stencil_ref = r300->stencil_ref;
CS_LOCALS(r300);
- BEGIN_CS(size);
- OUT_CS_REG(R300_FG_ALPHA_FUNC, dsa->alpha_function);
- OUT_CS_REG_SEQ(R300_ZB_CNTL, 3);
-
if (fb->zsbuf) {
- OUT_CS(dsa->z_buffer_control);
- OUT_CS(dsa->z_stencil_control);
+ WRITE_CS_TABLE(&dsa->cb_begin, size);
} else {
- OUT_CS(0);
- OUT_CS(0);
+ WRITE_CS_TABLE(dsa->cb_no_readwrite, size);
}
-
- OUT_CS(dsa->stencil_ref_mask | stencil_ref.ref_value[0]);
-
- if (r300->screen->caps.is_r500) {
- OUT_CS_REG(R500_ZB_STENCILREFMASK_BF, dsa->stencil_ref_bf | stencil_ref.ref_value[1]);
- }
- END_CS;
}
static const float * get_rc_constant_state(
@@ -175,7 +127,7 @@ static const float * get_rc_constant_state(
/* Convert a normal single-precision float into the 7.16 format
* used by the R300 fragment shader.
*/
-static uint32_t pack_float24(float f)
+uint32_t pack_float24(float f)
{
union {
float fl;
@@ -206,101 +158,27 @@ static uint32_t pack_float24(float f)
return float24;
}
-unsigned r300_get_fs_atom_size(struct r300_context *r300)
-{
- struct r300_fragment_shader *fs = r300_fs(r300);
- unsigned imm_count = fs->shader->immediates_count;
- struct r300_fragment_program_code *code = &fs->shader->code.code.r300;
-
- return 19 +
- code->alu.length * 4 +
- (code->tex.length ? (1 + code->tex.length) : 0) +
- (imm_count ? imm_count * 5 : 0);
-}
-
void r300_emit_fs(struct r300_context* r300, unsigned size, void *state)
{
struct r300_fragment_shader *fs = r300_fs(r300);
- struct rX00_fragment_program_code* generic_code = &fs->shader->code;
- struct r300_fragment_program_code * code = &generic_code->code.r300;
- unsigned i;
- unsigned imm_count = fs->shader->immediates_count;
- unsigned imm_first = fs->shader->externals_count;
- unsigned imm_end = generic_code->constants.Count;
- struct rc_constant *constants = generic_code->constants.Constants;
CS_LOCALS(r300);
- BEGIN_CS(size);
- OUT_CS_REG(R300_US_CONFIG, code->config);
- OUT_CS_REG(R300_US_PIXSIZE, code->pixsize);
- OUT_CS_REG(R300_US_CODE_OFFSET, code->code_offset);
-
- OUT_CS_REG_SEQ(R300_US_CODE_ADDR_0, 4);
- OUT_CS_TABLE(code->code_addr, 4);
-
- OUT_CS_REG_SEQ(R300_US_ALU_RGB_INST_0, code->alu.length);
- for (i = 0; i < code->alu.length; i++)
- OUT_CS(code->alu.inst[i].rgb_inst);
-
- OUT_CS_REG_SEQ(R300_US_ALU_RGB_ADDR_0, code->alu.length);
- for (i = 0; i < code->alu.length; i++)
- OUT_CS(code->alu.inst[i].rgb_addr);
-
- OUT_CS_REG_SEQ(R300_US_ALU_ALPHA_INST_0, code->alu.length);
- for (i = 0; i < code->alu.length; i++)
- OUT_CS(code->alu.inst[i].alpha_inst);
-
- OUT_CS_REG_SEQ(R300_US_ALU_ALPHA_ADDR_0, code->alu.length);
- for (i = 0; i < code->alu.length; i++)
- OUT_CS(code->alu.inst[i].alpha_addr);
-
- if (code->tex.length) {
- OUT_CS_REG_SEQ(R300_US_TEX_INST_0, code->tex.length);
- OUT_CS_TABLE(code->tex.inst, code->tex.length);
- }
-
- /* Emit immediates. */
- if (imm_count) {
- for(i = imm_first; i < imm_end; ++i) {
- if (constants[i].Type == RC_CONSTANT_IMMEDIATE) {
- const float *data = constants[i].u.Immediate;
-
- OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X + i * 16, 4);
- OUT_CS(pack_float24(data[0]));
- OUT_CS(pack_float24(data[1]));
- OUT_CS(pack_float24(data[2]));
- OUT_CS(pack_float24(data[3]));
- }
- }
- }
-
- OUT_CS_REG(R300_FG_DEPTH_SRC, fs->shader->fg_depth_src);
- OUT_CS_REG(R300_US_W_FMT, fs->shader->us_out_w);
- END_CS;
+ WRITE_CS_TABLE(fs->shader->cb_code, fs->shader->cb_code_size);
}
void r300_emit_fs_constants(struct r300_context* r300, unsigned size, void *state)
{
struct r300_fragment_shader *fs = r300_fs(r300);
- struct rc_constant_list *constants = &fs->shader->code.constants;
struct r300_constant_buffer *buf = (struct r300_constant_buffer*)state;
- unsigned i, count = fs->shader->externals_count;
+ unsigned count = fs->shader->externals_count * 4;
CS_LOCALS(r300);
if (count == 0)
return;
BEGIN_CS(size);
- OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X, count * 4);
- for(i = 0; i < count; ++i) {
- const float *data;
- assert(constants->Constants[i].Type == RC_CONSTANT_EXTERNAL);
- data = buf->constants[i];
- OUT_CS(pack_float24(data[0]));
- OUT_CS(pack_float24(data[1]));
- OUT_CS(pack_float24(data[2]));
- OUT_CS(pack_float24(data[3]));
- }
+ OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X, count);
+ OUT_CS_TABLE(buf->constants, count);
END_CS;
}
@@ -312,6 +190,8 @@ void r300_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, vo
unsigned count = fs->shader->rc_state_count;
unsigned first = fs->shader->externals_count;
unsigned end = constants->Count;
+ uint32_t cdata[4];
+ unsigned j;
CS_LOCALS(r300);
if (count == 0)
@@ -323,85 +203,29 @@ void r300_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, vo
const float *data =
get_rc_constant_state(r300, &constants->Constants[i]);
+ for (j = 0; j < 4; j++)
+ cdata[j] = pack_float24(data[j]);
+
OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X + i * 16, 4);
- OUT_CS(pack_float24(data[0]));
- OUT_CS(pack_float24(data[1]));
- OUT_CS(pack_float24(data[2]));
- OUT_CS(pack_float24(data[3]));
+ OUT_CS_TABLE(cdata, 4);
}
}
END_CS;
}
-unsigned r500_get_fs_atom_size(struct r300_context *r300)
-{
- struct r300_fragment_shader *fs = r300_fs(r300);
- unsigned imm_count = fs->shader->immediates_count;
- struct r500_fragment_program_code *code = &fs->shader->code.code.r500;
-
- return 17 +
- ((code->inst_end + 1) * 6) +
- (imm_count ? imm_count * 7 : 0);
-}
-
void r500_emit_fs(struct r300_context* r300, unsigned size, void *state)
{
struct r300_fragment_shader *fs = r300_fs(r300);
- struct rX00_fragment_program_code* generic_code = &fs->shader->code;
- struct r500_fragment_program_code * code = &generic_code->code.r500;
- unsigned i;
- unsigned imm_count = fs->shader->immediates_count;
- unsigned imm_first = fs->shader->externals_count;
- unsigned imm_end = generic_code->constants.Count;
- struct rc_constant *constants = generic_code->constants.Constants;
CS_LOCALS(r300);
- BEGIN_CS(size);
- OUT_CS_REG(R500_US_CONFIG, R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO);
- OUT_CS_REG(R500_US_PIXSIZE, code->max_temp_idx);
- OUT_CS_REG(R500_US_CODE_RANGE,
- R500_US_CODE_RANGE_ADDR(0) | R500_US_CODE_RANGE_SIZE(code->inst_end));
- OUT_CS_REG(R500_US_CODE_OFFSET, 0);
- OUT_CS_REG(R500_US_CODE_ADDR,
- R500_US_CODE_START_ADDR(0) | R500_US_CODE_END_ADDR(code->inst_end));
-
- OUT_CS_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_INSTR);
- OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, (code->inst_end + 1) * 6);
- for (i = 0; i <= code->inst_end; i++) {
- OUT_CS(code->inst[i].inst0);
- OUT_CS(code->inst[i].inst1);
- OUT_CS(code->inst[i].inst2);
- OUT_CS(code->inst[i].inst3);
- OUT_CS(code->inst[i].inst4);
- OUT_CS(code->inst[i].inst5);
- }
-
- /* Emit immediates. */
- if (imm_count) {
- for(i = imm_first; i < imm_end; ++i) {
- if (constants[i].Type == RC_CONSTANT_IMMEDIATE) {
- const float *data = constants[i].u.Immediate;
-
- OUT_CS_REG(R500_GA_US_VECTOR_INDEX,
- R500_GA_US_VECTOR_INDEX_TYPE_CONST |
- (i & R500_GA_US_VECTOR_INDEX_MASK));
- OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, 4);
- OUT_CS_TABLE(data, 4);
- }
- }
- }
-
- OUT_CS_REG(R300_FG_DEPTH_SRC, fs->shader->fg_depth_src);
- OUT_CS_REG(R300_US_W_FMT, fs->shader->us_out_w);
- END_CS;
+ WRITE_CS_TABLE(fs->shader->cb_code, fs->shader->cb_code_size);
}
void r500_emit_fs_constants(struct r300_context* r300, unsigned size, void *state)
{
struct r300_fragment_shader *fs = r300_fs(r300);
- struct rc_constant_list *constants = &fs->shader->code.constants;
struct r300_constant_buffer *buf = (struct r300_constant_buffer*)state;
- unsigned i, count = fs->shader->externals_count;
+ unsigned count = fs->shader->externals_count * 4;
CS_LOCALS(r300);
if (count == 0)
@@ -409,11 +233,8 @@ void r500_emit_fs_constants(struct r300_context* r300, unsigned size, void *stat
BEGIN_CS(size);
OUT_CS_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_CONST);
- OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, count * 4);
- for(i = 0; i < count; ++i) {
- assert(constants->Constants[i].Type == RC_CONSTANT_EXTERNAL);
- }
- OUT_CS_TABLE(buf->constants, count * 4);
+ OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, count);
+ OUT_CS_TABLE(buf->constants, count);
END_CS;
}
@@ -446,83 +267,170 @@ void r500_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, vo
END_CS;
}
+void r300_emit_gpu_flush(struct r300_context *r300, unsigned size, void *state)
+{
+ struct r300_gpu_flush *gpuflush = (struct r300_gpu_flush*)state;
+ struct pipe_framebuffer_state* fb =
+ (struct pipe_framebuffer_state*)r300->fb_state.state;
+ CS_LOCALS(r300);
+
+ BEGIN_CS(size);
+
+ /* Set up scissors.
+ * By writing to the SC registers, SC & US assert idle. */
+ OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2);
+ if (r300->screen->caps.is_r500) {
+ OUT_CS(0);
+ OUT_CS(((fb->width - 1) << R300_SCISSORS_X_SHIFT) |
+ ((fb->height - 1) << R300_SCISSORS_Y_SHIFT));
+ } else {
+ OUT_CS((1440 << R300_SCISSORS_X_SHIFT) |
+ (1440 << R300_SCISSORS_Y_SHIFT));
+ OUT_CS(((fb->width + 1440-1) << R300_SCISSORS_X_SHIFT) |
+ ((fb->height + 1440-1) << R300_SCISSORS_Y_SHIFT));
+ }
+
+ /* Flush CB & ZB caches and wait until the 3D engine is idle and clean. */
+ OUT_CS_TABLE(gpuflush->cb_flush_clean, 6);
+ END_CS;
+}
+
+void r300_emit_aa_state(struct r300_context *r300, unsigned size, void *state)
+{
+ struct r300_aa_state *aa = (struct r300_aa_state*)state;
+ CS_LOCALS(r300);
+
+ BEGIN_CS(size);
+ OUT_CS_REG(R300_GB_AA_CONFIG, aa->aa_config);
+
+ if (aa->dest) {
+ OUT_CS_REG_SEQ(R300_RB3D_AARESOLVE_OFFSET, 1);
+ OUT_CS_RELOC(aa->dest->buffer, aa->dest->offset, 0, aa->dest->domain, 0);
+
+ OUT_CS_REG_SEQ(R300_RB3D_AARESOLVE_PITCH, 1);
+ OUT_CS_RELOC(aa->dest->buffer, aa->dest->pitch, 0, aa->dest->domain, 0);
+ }
+
+ OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, aa->aaresolve_ctl);
+ END_CS;
+}
+
void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
{
struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)state;
- struct r300_texture* tex;
- struct pipe_surface* surf;
- int i;
+ struct r300_surface* surf;
+ unsigned i;
CS_LOCALS(r300);
BEGIN_CS(size);
- /* Flush and free renderbuffer caches. */
- OUT_CS_REG(R300_RB3D_DSTCACHE_CTLSTAT,
- R300_RB3D_DSTCACHE_CTLSTAT_DC_FREE_FREE_3D_TAGS |
- R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D);
- OUT_CS_REG(R300_ZB_ZCACHE_CTLSTAT,
- R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE |
- R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE);
-
- /* Set the number of colorbuffers. */
- if (fb->nr_cbufs > 1) {
- if (r300->screen->caps.is_r500) {
- OUT_CS_REG(R300_RB3D_CCTL,
- R300_RB3D_CCTL_NUM_MULTIWRITES(fb->nr_cbufs) |
- R300_RB3D_CCTL_INDEPENDENT_COLORFORMAT_ENABLE_ENABLE);
- } else {
- OUT_CS_REG(R300_RB3D_CCTL,
- R300_RB3D_CCTL_NUM_MULTIWRITES(fb->nr_cbufs));
- }
+ /* NUM_MULTIWRITES replicates COLOR[0] to all colorbuffers, which is not
+ * what we usually want. */
+ if (r300->screen->caps.is_r500) {
+ OUT_CS_REG(R300_RB3D_CCTL,
+ R300_RB3D_CCTL_INDEPENDENT_COLORFORMAT_ENABLE_ENABLE);
} else {
- OUT_CS_REG(R300_RB3D_CCTL, 0x0);
+ OUT_CS_REG(R300_RB3D_CCTL, 0);
}
/* Set up colorbuffers. */
for (i = 0; i < fb->nr_cbufs; i++) {
- surf = fb->cbufs[i];
- tex = r300_texture(surf->texture);
- assert(tex && tex->buffer && "cbuf is marked, but NULL!");
+ surf = r300_surface(fb->cbufs[i]);
OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0 + (4 * i), 1);
- OUT_CS_TEX_RELOC(tex, surf->offset, 0, tex->domain, 0);
+ OUT_CS_RELOC(surf->buffer, surf->offset, 0, surf->domain, 0);
OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0 + (4 * i), 1);
- OUT_CS_TEX_RELOC(tex, tex->fb_state.colorpitch[surf->level],
- 0, tex->domain, 0);
-
- OUT_CS_REG(R300_US_OUT_FMT_0 + (4 * i), tex->fb_state.us_out_fmt);
- }
- for (; i < 4; i++) {
- OUT_CS_REG(R300_US_OUT_FMT_0 + (4 * i), R300_US_OUT_FMT_UNUSED);
+ OUT_CS_RELOC(surf->buffer, surf->pitch, 0, surf->domain, 0);
}
/* Set up a zbuffer. */
if (fb->zsbuf) {
- surf = fb->zsbuf;
- tex = r300_texture(surf->texture);
- assert(tex && tex->buffer && "zsbuf is marked, but NULL!");
+ surf = r300_surface(fb->zsbuf);
- OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1);
- OUT_CS_TEX_RELOC(tex, surf->offset, 0, tex->domain, 0);
+ OUT_CS_REG(R300_ZB_FORMAT, surf->format);
- OUT_CS_REG(R300_ZB_FORMAT, tex->fb_state.zb_format);
+ OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1);
+ OUT_CS_RELOC(surf->buffer, surf->offset, 0, surf->domain, 0);
OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1);
- OUT_CS_TEX_RELOC(tex, tex->fb_state.depthpitch[surf->level],
- 0, tex->domain, 0);
+ OUT_CS_RELOC(surf->buffer, surf->pitch, 0, surf->domain, 0);
+
+ /* HiZ RAM. */
+ if (r300->screen->caps.has_hiz) {
+ OUT_CS_REG(R300_ZB_HIZ_OFFSET, 0);
+ OUT_CS_REG(R300_ZB_HIZ_PITCH, 0);
+ }
+
+ /* Z Mask RAM. (compressed zbuffer) */
+ OUT_CS_REG(R300_ZB_ZMASK_OFFSET, 0);
+ OUT_CS_REG(R300_ZB_ZMASK_PITCH, 0);
}
- OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2);
- if (r300->screen->caps.is_r500) {
- OUT_CS(0);
- OUT_CS(((fb->width - 1) << R300_SCISSORS_X_SHIFT) |
- ((fb->height - 1) << R300_SCISSORS_Y_SHIFT));
- } else {
- OUT_CS((1440 << R300_SCISSORS_X_SHIFT) |
- (1440 << R300_SCISSORS_Y_SHIFT));
- OUT_CS(((fb->width + 1440-1) << R300_SCISSORS_X_SHIFT) |
- ((fb->height + 1440-1) << R300_SCISSORS_Y_SHIFT));
+ END_CS;
+}
+
+void r300_emit_hyperz_state(struct r300_context *r300,
+ unsigned size, void *state)
+{
+ CS_LOCALS(r300);
+ WRITE_CS_TABLE(state, size);
+}
+
+void r300_emit_fb_state_pipelined(struct r300_context *r300,
+ unsigned size, void *state)
+{
+ struct pipe_framebuffer_state* fb =
+ (struct pipe_framebuffer_state*)r300->fb_state.state;
+ unsigned i;
+ CS_LOCALS(r300);
+
+ BEGIN_CS(size);
+
+ /* Colorbuffer format in the US block.
+ * (must be written after unpipelined regs) */
+ OUT_CS_REG_SEQ(R300_US_OUT_FMT_0, 4);
+ for (i = 0; i < fb->nr_cbufs; i++) {
+ OUT_CS(r300_surface(fb->cbufs[i])->format);
+ }
+ for (; i < 4; i++) {
+ OUT_CS(R300_US_OUT_FMT_UNUSED);
+ }
+
+ /* Multisampling. Depends on framebuffer sample count.
+ * These are pipelined regs and as such cannot be moved
+ * to the AA state. */
+ if (r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0)) {
+ unsigned mspos0 = 0x66666666;
+ unsigned mspos1 = 0x6666666;
+
+ if (fb->nr_cbufs && fb->cbufs[0]->texture->nr_samples > 1) {
+ /* Subsample placement. These may not be optimal. */
+ switch (fb->cbufs[0]->texture->nr_samples) {
+ case 2:
+ mspos0 = 0x33996633;
+ mspos1 = 0x6666663;
+ break;
+ case 3:
+ mspos0 = 0x33936933;
+ mspos1 = 0x6666663;
+ break;
+ case 4:
+ mspos0 = 0x33939933;
+ mspos1 = 0x3966663;
+ break;
+ case 6:
+ mspos0 = 0x22a2aa22;
+ mspos1 = 0x2a65672;
+ break;
+ default:
+ debug_printf("r300: Bad number of multisamples!\n");
+ }
+ }
+
+ OUT_CS_REG_SEQ(R300_GB_MSPOS0, 2);
+ OUT_CS(mspos0);
+ OUT_CS(mspos1);
}
END_CS;
}
@@ -544,13 +452,14 @@ void r300_emit_query_start(struct r300_context *r300, unsigned size, void*state)
OUT_CS_REG(R300_ZB_ZPASS_DATA, 0);
END_CS;
query->begin_emitted = TRUE;
+ query->flushed = FALSE;
}
-
static void r300_emit_query_end_frag_pipes(struct r300_context *r300,
struct r300_query *query)
{
struct r300_capabilities* caps = &r300->screen->caps;
+ struct r300_winsys_buffer *buf = r300->query_current->buffer;
CS_LOCALS(r300);
assert(caps->num_frag_pipes);
@@ -569,28 +478,28 @@ static void r300_emit_query_end_frag_pipes(struct r300_context *r300,
/* pipe 3 only */
OUT_CS_REG(R300_SU_REG_DEST, 1 << 3);
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
- OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 3),
- 0, r300_buffer(r300->oqbo)->domain, 0);
+ OUT_CS_RELOC(buf, (query->num_results + 3) * 4,
+ 0, query->domain, 0);
case 3:
/* pipe 2 only */
OUT_CS_REG(R300_SU_REG_DEST, 1 << 2);
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
- OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 2),
- 0, r300_buffer(r300->oqbo)->domain, 0);
+ OUT_CS_RELOC(buf, (query->num_results + 2) * 4,
+ 0, query->domain, 0);
case 2:
/* pipe 1 only */
/* As mentioned above, accomodate RV380 and older. */
OUT_CS_REG(R300_SU_REG_DEST,
1 << (caps->high_second_pipe ? 3 : 1));
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
- OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 1),
- 0, r300_buffer(r300->oqbo)->domain, 0);
+ OUT_CS_RELOC(buf, (query->num_results + 1) * 4,
+ 0, query->domain, 0);
case 1:
/* pipe 0 only */
OUT_CS_REG(R300_SU_REG_DEST, 1 << 0);
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
- OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 0),
- 0, r300_buffer(r300->oqbo)->domain, 0);
+ OUT_CS_RELOC(buf, (query->num_results + 0) * 4,
+ 0, query->domain, 0);
break;
default:
fprintf(stderr, "r300: Implementation error: Chipset reports %d"
@@ -606,12 +515,13 @@ static void r300_emit_query_end_frag_pipes(struct r300_context *r300,
static void rv530_emit_query_end_single_z(struct r300_context *r300,
struct r300_query *query)
{
+ struct r300_winsys_buffer *buf = r300->query_current->buffer;
CS_LOCALS(r300);
BEGIN_CS(8);
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0);
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
- OUT_CS_BUF_RELOC(r300->oqbo, query->offset, 0, r300_buffer(r300->oqbo)->domain, 0);
+ OUT_CS_RELOC(buf, query->num_results * 4, 0, query->domain, 0);
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
END_CS;
}
@@ -619,15 +529,16 @@ static void rv530_emit_query_end_single_z(struct r300_context *r300,
static void rv530_emit_query_end_double_z(struct r300_context *r300,
struct r300_query *query)
{
+ struct r300_winsys_buffer *buf = r300->query_current->buffer;
CS_LOCALS(r300);
BEGIN_CS(14);
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0);
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
- OUT_CS_BUF_RELOC(r300->oqbo, query->offset, 0, r300_buffer(r300->oqbo)->domain, 0);
+ OUT_CS_RELOC(buf, (query->num_results + 0) * 4, 0, query->domain, 0);
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_1);
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
- OUT_CS_BUF_RELOC(r300->oqbo, query->offset + sizeof(uint32_t), 0, r300_buffer(r300->oqbo)->domain, 0);
+ OUT_CS_RELOC(buf, (query->num_results + 1) * 4, 0, query->domain, 0);
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
END_CS;
}
@@ -652,57 +563,36 @@ void r300_emit_query_end(struct r300_context* r300)
r300_emit_query_end_frag_pipes(r300, query);
query->begin_emitted = FALSE;
+ query->num_results += query->num_pipes;
+
+ /* XXX grab all the results and reset the counter. */
+ if (query->num_results >= query->buffer_size / 4 - 4) {
+ query->num_results = (query->buffer_size / 4) / 2;
+ fprintf(stderr, "r300: Rewinding OQBO...\n");
+ }
+}
+
+void r300_emit_invariant_state(struct r300_context *r300,
+ unsigned size, void *state)
+{
+ CS_LOCALS(r300);
+ WRITE_CS_TABLE(state, size);
}
void r300_emit_rs_state(struct r300_context* r300, unsigned size, void* state)
{
- struct r300_rs_state* rs = (struct r300_rs_state*)state;
- float scale, offset;
+ struct r300_rs_state* rs = state;
CS_LOCALS(r300);
BEGIN_CS(size);
- OUT_CS_REG(R300_VAP_CNTL_STATUS, rs->vap_control_status);
-
- OUT_CS_REG(R300_GB_AA_CONFIG, rs->antialiasing_config);
-
- OUT_CS_REG(R300_GA_POINT_SIZE, rs->point_size);
- OUT_CS_REG_SEQ(R300_GA_POINT_MINMAX, 2);
- OUT_CS(rs->point_minmax);
- OUT_CS(rs->line_control);
-
+ OUT_CS_TABLE(rs->cb_main, 25);
if (rs->polygon_offset_enable) {
- scale = rs->depth_scale * 12;
- offset = rs->depth_offset;
-
- switch (r300->zbuffer_bpp) {
- case 16:
- offset *= 4;
- break;
- case 24:
- offset *= 2;
- break;
+ if (r300->zbuffer_bpp == 16) {
+ OUT_CS_TABLE(rs->cb_poly_offset_zb16, 5);
+ } else {
+ OUT_CS_TABLE(rs->cb_poly_offset_zb24, 5);
}
-
- OUT_CS_REG_SEQ(R300_SU_POLY_OFFSET_FRONT_SCALE, 4);
- OUT_CS_32F(scale);
- OUT_CS_32F(offset);
- OUT_CS_32F(scale);
- OUT_CS_32F(offset);
}
-
- OUT_CS_REG_SEQ(R300_SU_POLY_OFFSET_ENABLE, 2);
- OUT_CS(rs->polygon_offset_enable);
- OUT_CS(rs->cull_mode);
- OUT_CS_REG(R300_GA_LINE_STIPPLE_CONFIG, rs->line_stipple_config);
- OUT_CS_REG(R300_GA_LINE_STIPPLE_VALUE, rs->line_stipple_value);
- OUT_CS_REG(R300_GA_POLY_MODE, rs->polygon_mode);
- OUT_CS_REG(R300_SC_CLIP_RULE, rs->clip_rule);
- OUT_CS_REG(R300_GB_ENABLE, rs->stuffing_enable);
- OUT_CS_REG_SEQ(R300_GA_POINT_S0, 4);
- OUT_CS_32F(rs->point_texcoord_left);
- OUT_CS_32F(rs->point_texcoord_bottom);
- OUT_CS_32F(rs->point_texcoord_right);
- OUT_CS_32F(rs->point_texcoord_top);
END_CS;
}
@@ -717,9 +607,18 @@ void r300_emit_rs_block_state(struct r300_context* r300,
if (SCREEN_DBG_ON(r300->screen, DBG_DRAW)) {
r500_dump_rs_block(rs);
- }
- DBG(r300, DBG_DRAW, "r300: RS emit:\n");
+ fprintf(stderr, "r300: RS emit:\n");
+
+ for (i = 0; i < count; i++)
+ fprintf(stderr, " : ip %d: 0x%08x\n", i, rs->ip[i]);
+
+ for (i = 0; i < count; i++)
+ fprintf(stderr, " : inst %d: 0x%08x\n", i, rs->inst[i]);
+
+ fprintf(stderr, " : count: 0x%08x inst_count: 0x%08x\n",
+ rs->count, rs->inst_count);
+ }
BEGIN_CS(size);
OUT_CS_REG_SEQ(R300_VAP_VTX_STATE_CNTL, 2);
@@ -735,9 +634,6 @@ void r300_emit_rs_block_state(struct r300_context* r300,
OUT_CS_REG_SEQ(R300_RS_IP_0, count);
}
OUT_CS_TABLE(rs->ip, count);
- for (i = 0; i < count; i++) {
- DBG(r300, DBG_DRAW, " : ip %d: 0x%08x\n", i, rs->ip[i]);
- }
OUT_CS_REG_SEQ(R300_RS_COUNT, 2);
OUT_CS(rs->count);
@@ -749,13 +645,6 @@ void r300_emit_rs_block_state(struct r300_context* r300,
OUT_CS_REG_SEQ(R300_RS_INST_0, count);
}
OUT_CS_TABLE(rs->inst, count);
- for (i = 0; i < count; i++) {
- DBG(r300, DBG_DRAW, " : inst %d: 0x%08x\n", i, rs->inst[i]);
- }
-
- DBG(r300, DBG_DRAW, " : count: 0x%08x inst_count: 0x%08x\n",
- rs->count, rs->inst_count);
-
END_CS;
}
@@ -821,19 +710,11 @@ void r300_emit_aos(struct r300_context* r300, int offset, boolean indexed)
struct pipe_vertex_element *velem = r300->velems->velem;
struct r300_buffer *buf;
int i;
+ unsigned *hw_format_size = r300->velems->hw_format_size;
unsigned size1, size2, aos_count = r300->velems->count;
unsigned packet_size = (aos_count * 3 + 1) / 2;
CS_LOCALS(r300);
- for (i = 0; i < aos_count; i++) {
- if ((vbuf[velem[i].vertex_buffer_index].buffer_offset + velem[i].src_offset) % 4 != 0) {
- /* XXX We must align the buffer. */
- assert(0);
- fprintf(stderr, "r300: Unaligned vertex buffer offsets aren't supported, aborting..\n");
- abort();
- }
- }
-
BEGIN_CS(2 + packet_size + aos_count * 2);
OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, packet_size);
OUT_CS(aos_count | (!indexed ? R300_VC_FORCE_PREFETCH : 0));
@@ -841,8 +722,8 @@ void r300_emit_aos(struct r300_context* r300, int offset, boolean indexed)
for (i = 0; i < aos_count - 1; i += 2) {
vb1 = &vbuf[velem[i].vertex_buffer_index];
vb2 = &vbuf[velem[i+1].vertex_buffer_index];
- size1 = util_format_get_blocksize(velem[i].src_format);
- size2 = util_format_get_blocksize(velem[i+1].src_format);
+ size1 = hw_format_size[i];
+ size2 = hw_format_size[i+1];
OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride) |
R300_VBPNTR_SIZE1(size2) | R300_VBPNTR_STRIDE1(vb2->stride));
@@ -852,7 +733,7 @@ void r300_emit_aos(struct r300_context* r300, int offset, boolean indexed)
if (aos_count & 1) {
vb1 = &vbuf[velem[i].vertex_buffer_index];
- size1 = util_format_get_blocksize(velem[i].src_format);
+ size1 = hw_format_size[i];
OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride));
OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride);
@@ -897,21 +778,25 @@ void r300_emit_vertex_stream_state(struct r300_context* r300,
unsigned i;
CS_LOCALS(r300);
- DBG(r300, DBG_DRAW, "r300: PSC emit:\n");
+ if (DBG_ON(r300, DBG_DRAW)) {
+ fprintf(stderr, "r300: PSC emit:\n");
+
+ for (i = 0; i < streams->count; i++) {
+ fprintf(stderr, " : prog_stream_cntl%d: 0x%08x\n", i,
+ streams->vap_prog_stream_cntl[i]);
+ }
+
+ for (i = 0; i < streams->count; i++) {
+ fprintf(stderr, " : prog_stream_cntl_ext%d: 0x%08x\n", i,
+ streams->vap_prog_stream_cntl_ext[i]);
+ }
+ }
BEGIN_CS(size);
OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_0, streams->count);
OUT_CS_TABLE(streams->vap_prog_stream_cntl, streams->count);
- for (i = 0; i < streams->count; i++) {
- DBG(r300, DBG_DRAW, " : prog_stream_cntl%d: 0x%08x\n", i,
- streams->vap_prog_stream_cntl[i]);
- }
OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_EXT_0, streams->count);
OUT_CS_TABLE(streams->vap_prog_stream_cntl_ext, streams->count);
- for (i = 0; i < streams->count; i++) {
- DBG(r300, DBG_DRAW, " : prog_stream_cntl_ext%d: 0x%08x\n", i,
- streams->vap_prog_stream_cntl_ext[i]);
- }
END_CS;
}
@@ -924,6 +809,13 @@ void r300_emit_pvs_flush(struct r300_context* r300, unsigned size, void* state)
END_CS;
}
+void r300_emit_vap_invariant_state(struct r300_context *r300,
+ unsigned size, void *state)
+{
+ CS_LOCALS(r300);
+ WRITE_CS_TABLE(state, size);
+}
+
void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state)
{
struct r300_vertex_shader* vs = (struct r300_vertex_shader*)state;
@@ -948,6 +840,7 @@ void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state)
CS_LOCALS(r300);
BEGIN_CS(size);
+
/* R300_VAP_PVS_CODE_CNTL_0
* R300_VAP_PVS_CONST_CNTL
* R300_VAP_PVS_CODE_CNTL_1
@@ -1012,12 +905,7 @@ void r300_emit_viewport_state(struct r300_context* r300,
BEGIN_CS(size);
OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6);
- OUT_CS_32F(viewport->xscale);
- OUT_CS_32F(viewport->xoffset);
- OUT_CS_32F(viewport->yscale);
- OUT_CS_32F(viewport->yoffset);
- OUT_CS_32F(viewport->zscale);
- OUT_CS_32F(viewport->zoffset);
+ OUT_CS_TABLE(&viewport->xscale, 6);
OUT_CS_REG(R300_VAP_VTE_CNTL, viewport->vte_control);
END_CS;
}
@@ -1099,10 +987,9 @@ validate:
}
}
/* ...occlusion query buffer... */
- if (r300->query_start.dirty ||
- (r300->query_current && r300->query_current->begin_emitted)) {
- if (!r300_add_buffer(r300->rws, r300->oqbo,
- 0, r300_buffer(r300->oqbo)->domain)) {
+ if (r300->query_current) {
+ if (!r300->rws->add_buffer(r300->rws, r300->query_current->buffer,
+ 0, r300->query_current->domain)) {
r300->context.flush(&r300->context, 0, NULL);
goto validate;
}
diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h
index 9066088342..586ccda620 100644
--- a/src/gallium/drivers/r300/r300_emit.h
+++ b/src/gallium/drivers/r300/r300_emit.h
@@ -29,6 +29,8 @@
struct rX00_fragment_program_code;
struct r300_vertex_program_code;
+uint32_t pack_float24(float f);
+
void r300_emit_aos(struct r300_context* r300, int offset, boolean indexed);
void r300_emit_blend_state(struct r300_context* r300,
@@ -43,16 +45,12 @@ void r300_emit_clip_state(struct r300_context* r300,
void r300_emit_dsa_state(struct r300_context* r300,
unsigned size, void* state);
-unsigned r300_get_fs_atom_size(struct r300_context *r300);
-
void r300_emit_fs(struct r300_context* r300, unsigned size, void *state);
void r300_emit_fs_constants(struct r300_context* r300, unsigned size, void *state);
void r300_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, void *state);
-unsigned r500_get_fs_atom_size(struct r300_context *r300);
-
void r500_emit_fs(struct r300_context* r300, unsigned size, void *state);
void r500_emit_fs_constants(struct r300_context* r300, unsigned size, void *state);
@@ -61,6 +59,16 @@ void r500_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, vo
void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state);
+void r300_emit_fb_state_pipelined(struct r300_context *r300,
+ unsigned size, void *state);
+
+void r300_emit_gpu_flush(struct r300_context *r300, unsigned size, void *state);
+
+void r300_emit_hyperz_state(struct r300_context *r300,
+ unsigned size, void *state);
+
+void r300_emit_aa_state(struct r300_context *r300, unsigned size, void *state);
+
void r300_emit_query_start(struct r300_context *r300, unsigned size, void *state);
void r300_emit_query_end(struct r300_context* r300);
@@ -78,6 +86,9 @@ void r300_emit_textures_state(struct r300_context *r300,
void r300_emit_aos_swtcl(struct r300_context *r300, boolean indexed);
+void r300_emit_vap_invariant_state(struct r300_context *r300,
+ unsigned size, void *state);
+
void r300_emit_vertex_stream_state(struct r300_context* r300,
unsigned size, void* state);
@@ -96,6 +107,9 @@ void r300_emit_pvs_flush(struct r300_context* r300, unsigned size, void* state);
void r300_emit_texture_cache_inval(struct r300_context* r300, unsigned size, void* state);
+void r300_emit_invariant_state(struct r300_context *r300,
+ unsigned size, void *state);
+
unsigned r300_get_num_dirty_dwords(struct r300_context *r300);
/* Emit all dirty state. */
diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c
index 360b19a0c1..ba840bfff8 100644
--- a/src/gallium/drivers/r300/r300_flush.c
+++ b/src/gallium/drivers/r300/r300_flush.c
@@ -39,8 +39,6 @@ static void r300_flush(struct pipe_context* pipe,
struct r300_atom *atom;
struct r300_fence **rfence = (struct r300_fence**)fence;
- CS_LOCALS(r300);
- (void) cs_count;
/* We probably need to flush Draw, but we may have been called from
* within Draw. This feels kludgy, but it might be the best thing.
*
@@ -52,7 +50,10 @@ static void r300_flush(struct pipe_context* pipe,
if (r300->dirty_hw) {
r300_emit_query_end(r300);
- FLUSH_CS;
+ if (SCREEN_DBG_ON(r300->screen, DBG_STATS)) {
+ r300->flush_counter++;
+ }
+ r300->rws->flush_cs(r300->rws);
r300->dirty_hw = 0;
/* New kitchen sink, baby. */
diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c
index a434808046..424f831731 100644
--- a/src/gallium/drivers/r300/r300_fs.c
+++ b/src/gallium/drivers/r300/r300_fs.c
@@ -28,7 +28,9 @@
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_ureg.h"
+#include "r300_cb.h"
#include "r300_context.h"
+#include "r300_emit.h"
#include "r300_screen.h"
#include "r300_fs.h"
#include "r300_reg.h"
@@ -229,6 +231,122 @@ static void r300_dummy_fragment_shader(
ureg_destroy(ureg);
}
+static void r300_emit_fs_code_to_buffer(
+ struct r300_context *r300,
+ struct r300_fragment_shader_code *shader)
+{
+ struct rX00_fragment_program_code *generic_code = &shader->code;
+ unsigned imm_count = shader->immediates_count;
+ unsigned imm_first = shader->externals_count;
+ unsigned imm_end = generic_code->constants.Count;
+ struct rc_constant *constants = generic_code->constants.Constants;
+ unsigned i;
+ CB_LOCALS;
+
+ if (r300->screen->caps.is_r500) {
+ struct r500_fragment_program_code *code = &generic_code->code.r500;
+
+ shader->cb_code_size = 17 +
+ ((code->inst_end + 1) * 6) +
+ imm_count * 7;
+
+ NEW_CB(shader->cb_code, shader->cb_code_size);
+ OUT_CB_REG(R500_US_CONFIG, R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO);
+ OUT_CB_REG(R500_US_PIXSIZE, code->max_temp_idx);
+ OUT_CB_REG(R500_US_CODE_RANGE,
+ R500_US_CODE_RANGE_ADDR(0) | R500_US_CODE_RANGE_SIZE(code->inst_end));
+ OUT_CB_REG(R500_US_CODE_OFFSET, 0);
+ OUT_CB_REG(R500_US_CODE_ADDR,
+ R500_US_CODE_START_ADDR(0) | R500_US_CODE_END_ADDR(code->inst_end));
+
+ OUT_CB_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_INSTR);
+ OUT_CB_ONE_REG(R500_GA_US_VECTOR_DATA, (code->inst_end + 1) * 6);
+ for (i = 0; i <= code->inst_end; i++) {
+ OUT_CB(code->inst[i].inst0);
+ OUT_CB(code->inst[i].inst1);
+ OUT_CB(code->inst[i].inst2);
+ OUT_CB(code->inst[i].inst3);
+ OUT_CB(code->inst[i].inst4);
+ OUT_CB(code->inst[i].inst5);
+ }
+
+ /* Emit immediates. */
+ if (imm_count) {
+ for(i = imm_first; i < imm_end; ++i) {
+ if (constants[i].Type == RC_CONSTANT_IMMEDIATE) {
+ const float *data = constants[i].u.Immediate;
+
+ OUT_CB_REG(R500_GA_US_VECTOR_INDEX,
+ R500_GA_US_VECTOR_INDEX_TYPE_CONST |
+ (i & R500_GA_US_VECTOR_INDEX_MASK));
+ OUT_CB_ONE_REG(R500_GA_US_VECTOR_DATA, 4);
+ OUT_CB_TABLE(data, 4);
+ }
+ }
+ }
+ } else { /* r300 */
+ struct r300_fragment_program_code *code = &generic_code->code.r300;
+
+ shader->cb_code_size = 19 +
+ (r300->screen->caps.is_r400 ? 2 : 0) +
+ code->alu.length * 4 +
+ (code->tex.length ? (1 + code->tex.length) : 0) +
+ imm_count * 5;
+
+ NEW_CB(shader->cb_code, shader->cb_code_size);
+
+ if (r300->screen->caps.is_r400)
+ OUT_CB_REG(R400_US_CODE_BANK, 0);
+
+ OUT_CB_REG(R300_US_CONFIG, code->config);
+ OUT_CB_REG(R300_US_PIXSIZE, code->pixsize);
+ OUT_CB_REG(R300_US_CODE_OFFSET, code->code_offset);
+
+ OUT_CB_REG_SEQ(R300_US_CODE_ADDR_0, 4);
+ OUT_CB_TABLE(code->code_addr, 4);
+
+ OUT_CB_REG_SEQ(R300_US_ALU_RGB_INST_0, code->alu.length);
+ for (i = 0; i < code->alu.length; i++)
+ OUT_CB(code->alu.inst[i].rgb_inst);
+
+ OUT_CB_REG_SEQ(R300_US_ALU_RGB_ADDR_0, code->alu.length);
+ for (i = 0; i < code->alu.length; i++)
+ OUT_CB(code->alu.inst[i].rgb_addr);
+
+ OUT_CB_REG_SEQ(R300_US_ALU_ALPHA_INST_0, code->alu.length);
+ for (i = 0; i < code->alu.length; i++)
+ OUT_CB(code->alu.inst[i].alpha_inst);
+
+ OUT_CB_REG_SEQ(R300_US_ALU_ALPHA_ADDR_0, code->alu.length);
+ for (i = 0; i < code->alu.length; i++)
+ OUT_CB(code->alu.inst[i].alpha_addr);
+
+ if (code->tex.length) {
+ OUT_CB_REG_SEQ(R300_US_TEX_INST_0, code->tex.length);
+ OUT_CB_TABLE(code->tex.inst, code->tex.length);
+ }
+
+ /* Emit immediates. */
+ if (imm_count) {
+ for(i = imm_first; i < imm_end; ++i) {
+ if (constants[i].Type == RC_CONSTANT_IMMEDIATE) {
+ const float *data = constants[i].u.Immediate;
+
+ OUT_CB_REG_SEQ(R300_PFS_PARAM_0_X + i * 16, 4);
+ OUT_CB(pack_float24(data[0]));
+ OUT_CB(pack_float24(data[1]));
+ OUT_CB(pack_float24(data[2]));
+ OUT_CB(pack_float24(data[3]));
+ }
+ }
+ }
+ }
+
+ OUT_CB_REG(R300_FG_DEPTH_SRC, shader->fg_depth_src);
+ OUT_CB_REG(R300_US_W_FMT, shader->us_out_w);
+ END_CB;
+}
+
static void r300_translate_fragment_shader(
struct r300_context* r300,
struct r300_fragment_shader_code* shader,
@@ -338,6 +456,9 @@ static void r300_translate_fragment_shader(
/* And, finally... */
rc_destroy(&compiler.Base);
+
+ /* Build the command buffer. */
+ r300_emit_fs_code_to_buffer(r300, shader);
}
boolean r300_pick_fragment_shader(struct r300_context* r300)
diff --git a/src/gallium/drivers/r300/r300_fs.h b/src/gallium/drivers/r300/r300_fs.h
index 1cc4355359..51bfa88c5e 100644
--- a/src/gallium/drivers/r300/r300_fs.h
+++ b/src/gallium/drivers/r300/r300_fs.h
@@ -50,6 +50,9 @@ struct r300_fragment_shader_code {
struct r300_fragment_program_external_state compare_state;
struct rX00_fragment_program_code code;
+ unsigned cb_code_size;
+ uint32_t *cb_code;
+
struct r300_fragment_shader_code* next;
};
diff --git a/src/gallium/drivers/r300/r300_hyperz.c b/src/gallium/drivers/r300/r300_hyperz.c
index b41b6b1508..e5c7658952 100644
--- a/src/gallium/drivers/r300/r300_hyperz.c
+++ b/src/gallium/drivers/r300/r300_hyperz.c
@@ -31,33 +31,46 @@
/* The ZTOP state */
/*****************************************************************************/
-static boolean r300_dsa_writes_depth_stencil(struct r300_dsa_state* dsa)
+static boolean r300_dsa_writes_stencil(
+ struct pipe_stencil_state *s)
{
- /* We are interested only in the cases when a new depth or stencil value
- * can be written and changed. */
+ return s->enabled && s->writemask &&
+ (s->fail_op != PIPE_STENCIL_OP_KEEP ||
+ s->zfail_op != PIPE_STENCIL_OP_KEEP ||
+ s->zpass_op != PIPE_STENCIL_OP_KEEP);
+}
+
+static boolean r300_dsa_writes_depth_stencil(
+ struct pipe_depth_stencil_alpha_state *dsa)
+{
+ /* We are interested only in the cases when a depth or stencil value
+ * can be changed. */
+
+ if (dsa->depth.enabled && dsa->depth.writemask &&
+ dsa->depth.func != PIPE_FUNC_NEVER)
+ return TRUE;
+
+ if (r300_dsa_writes_stencil(&dsa->stencil[0]) ||
+ r300_dsa_writes_stencil(&dsa->stencil[1]))
+ return TRUE;
- /* We might optionally check for [Z func: never] and inspect the stencil
- * state in a similar fashion, but it's not terribly important. */
- return (dsa->z_buffer_control & R300_Z_WRITE_ENABLE) ||
- (dsa->stencil_ref_mask & R300_STENCILWRITEMASK_MASK) ||
- ((dsa->z_buffer_control & R500_STENCIL_REFMASK_FRONT_BACK) &&
- (dsa->stencil_ref_bf & R300_STENCILWRITEMASK_MASK));
+ return FALSE;
}
-static boolean r300_dsa_alpha_test_enabled(struct r300_dsa_state* dsa)
+static boolean r300_dsa_alpha_test_enabled(
+ struct pipe_depth_stencil_alpha_state *dsa)
{
/* We are interested only in the cases when alpha testing can kill
* a fragment. */
- uint32_t af = dsa->alpha_function;
- return (af & R300_FG_ALPHA_FUNC_ENABLE) &&
- (af & R300_FG_ALPHA_FUNC_ALWAYS) != R300_FG_ALPHA_FUNC_ALWAYS;
+ return dsa->alpha.enabled && dsa->alpha.func != PIPE_FUNC_ALWAYS;
}
static void r300_update_ztop(struct r300_context* r300)
{
struct r300_ztop_state* ztop_state =
(struct r300_ztop_state*)r300->ztop_state.state;
+ uint32_t old_ztop = ztop_state->z_buffer_top;
/* This is important enough that I felt it warranted a comment.
*
@@ -99,7 +112,8 @@ static void r300_update_ztop(struct r300_context* r300)
ztop_state->z_buffer_top = R300_ZTOP_ENABLE;
}
- r300->ztop_state.dirty = TRUE;
+ if (ztop_state->z_buffer_top != old_ztop)
+ r300->ztop_state.dirty = TRUE;
}
void r300_update_hyperz_state(struct r300_context* r300)
diff --git a/src/gallium/drivers/r300/r300_query.c b/src/gallium/drivers/r300/r300_query.c
index 97081c4a00..10086ee925 100644
--- a/src/gallium/drivers/r300/r300_query.c
+++ b/src/gallium/drivers/r300/r300_query.c
@@ -26,6 +26,7 @@
#include "r300_context.h"
#include "r300_screen.h"
#include "r300_emit.h"
+#include "r300_winsys.h"
#include <stdio.h>
@@ -34,30 +35,29 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe,
{
struct r300_context *r300 = r300_context(pipe);
struct r300_screen *r300screen = r300->screen;
- unsigned query_size;
- struct r300_query *q, *qptr;
+ struct r300_query *q;
+
+ if (query_type != PIPE_QUERY_OCCLUSION_COUNTER) {
+ return NULL;
+ }
q = CALLOC_STRUCT(r300_query);
+ if (!q)
+ return NULL;
q->type = query_type;
- assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER);
+ q->domain = R300_DOMAIN_GTT;
+ q->buffer_size = 4096;
if (r300screen->caps.family == CHIP_FAMILY_RV530)
- query_size = r300screen->caps.num_z_pipes * sizeof(uint32_t);
+ q->num_pipes = r300screen->caps.num_z_pipes;
else
- query_size = r300screen->caps.num_frag_pipes * sizeof(uint32_t);
+ q->num_pipes = r300screen->caps.num_frag_pipes;
- if (!is_empty_list(&r300->query_list)) {
- qptr = last_elem(&r300->query_list);
- q->offset = qptr->offset + query_size;
- }
insert_at_tail(&r300->query_list, q);
- /* XXX */
- if (q->offset >= 4096) {
- q->offset = 0;
- fprintf(stderr, "r300: Rewinding OQBO...\n");
- }
+ /* Open up the occlusion query buffer. */
+ q->buffer = r300->rws->buffer_create(r300->rws, 4096, 0, q->domain, q->buffer_size);
return (struct pipe_query*)q;
}
@@ -65,18 +65,26 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe,
static void r300_destroy_query(struct pipe_context* pipe,
struct pipe_query* query)
{
- struct r300_query* q = (struct r300_query*)query;
+ struct r300_context *r300 = r300_context(pipe);
+ struct r300_query* q = r300_query(query);
+ r300->rws->buffer_reference(r300->rws, &q->buffer, NULL);
remove_from_list(q);
FREE(query);
}
+void r300_resume_query(struct r300_context *r300,
+ struct r300_query *query)
+{
+ r300->query_current = query;
+ r300->query_start.dirty = TRUE;
+}
+
static void r300_begin_query(struct pipe_context* pipe,
struct pipe_query* query)
{
- uint32_t value = ~0U;
struct r300_context* r300 = r300_context(pipe);
- struct r300_query* q = (struct r300_query*)query;
+ struct r300_query* q = r300_query(query);
if (r300->query_current != NULL) {
fprintf(stderr, "r300: begin_query: "
@@ -85,85 +93,59 @@ static void r300_begin_query(struct pipe_context* pipe,
return;
}
- pipe_buffer_write(pipe,
- r300->oqbo,
- q->offset,
- sizeof value,
- &value);
+ q->num_results = 0;
+ r300_resume_query(r300, q);
+}
- q->flushed = FALSE;
- r300->query_current = q;
- r300->query_start.dirty = TRUE;
+void r300_stop_query(struct r300_context *r300)
+{
+ r300_emit_query_end(r300);
+ r300->query_current = NULL;
}
static void r300_end_query(struct pipe_context* pipe,
struct pipe_query* query)
{
struct r300_context* r300 = r300_context(pipe);
+ struct r300_query *q = r300_query(query);
- if ((struct r300_query*)query != r300->query_current) {
+ if (q != r300->query_current) {
fprintf(stderr, "r300: end_query: Got invalid query.\n");
assert(0);
return;
}
- r300_emit_query_end(r300);
- r300->query_current = NULL;
+ r300_stop_query(r300);
}
static boolean r300_get_query_result(struct pipe_context* pipe,
struct pipe_query* query,
boolean wait,
- uint64_t* result)
+ void* vresult)
{
struct r300_context* r300 = r300_context(pipe);
- struct r300_screen* r300screen = r300->screen;
- struct r300_query *q = (struct r300_query*)query;
- struct pipe_transfer *transfer;
- unsigned flags = PIPE_TRANSFER_READ;
- uint32_t* map;
- uint32_t temp = 0;
- unsigned i, num_results;
-
- if (q->flushed == FALSE)
+ struct r300_query *q = r300_query(query);
+ unsigned flags, i;
+ uint32_t temp, *map;
+ uint64_t *result = (uint64_t*)vresult;
+
+ if (!q->flushed)
pipe->flush(pipe, 0, NULL);
- if (!wait) {
- flags |= PIPE_TRANSFER_DONTBLOCK;
- }
- map = pipe_buffer_map(pipe, r300->oqbo, flags, &transfer);
+ flags = PIPE_TRANSFER_READ | (!wait ? PIPE_TRANSFER_DONTBLOCK : 0);
+
+ map = r300->rws->buffer_map(r300->rws, q->buffer, flags);
if (!map)
return FALSE;
- map += q->offset / 4;
- if (r300screen->caps.family == CHIP_FAMILY_RV530)
- num_results = r300screen->caps.num_z_pipes;
- else
- num_results = r300screen->caps.num_frag_pipes;
-
- for (i = 0; i < num_results; i++) {
- if (*map == ~0U) {
- /* Looks like our results aren't ready yet. */
- if (wait) {
- fprintf(stderr, "r300: Despite waiting, OQ results haven't "
- "come in yet. This is a driver bug.\n"
- "r300: Returning bogus results to avoid "
- "a possible infinite loop...\n");
- temp = 987654321;
- } else {
- temp = ~0U;
- }
- break;
- }
+ /* Sum up the results. */
+ temp = 0;
+ for (i = 0; i < q->num_results; i++) {
temp += *map;
map++;
}
- pipe_buffer_unmap(pipe, r300->oqbo, transfer);
- if (temp == ~0U) {
- /* Our results haven't been written yet... */
- return FALSE;
- }
+ r300->rws->buffer_unmap(r300->rws, q->buffer);
*result = temp;
return TRUE;
@@ -191,11 +173,61 @@ static void r300_render_condition(struct pipe_context *pipe,
}
}
+/***************************************************************************
+ * Fake occlusion queries (for debugging)
+ ***************************************************************************/
+
+static unsigned r300_fake_query;
+
+static struct pipe_query *r300_fake_create_query(struct pipe_context *pipe,
+ unsigned query_type)
+{
+ return (struct pipe_query*)&r300_fake_query;
+}
+
+static void r300_fake_destroy_query(struct pipe_context* pipe,
+ struct pipe_query* query)
+{
+}
+
+static void r300_fake_begin_query(struct pipe_context* pipe,
+ struct pipe_query* query)
+{
+}
+
+static void r300_fake_end_query(struct pipe_context* pipe,
+ struct pipe_query* query)
+{
+}
+
+static boolean r300_fake_get_query_result(struct pipe_context* pipe,
+ struct pipe_query* query,
+ boolean wait, void* vresult)
+{
+ uint64_t *result = (uint64_t*)vresult;
+ *result = 1000000;
+ return TRUE;
+}
+
+static void r300_fake_render_condition(struct pipe_context *pipe,
+ struct pipe_query *query, uint mode)
+{
+}
+
void r300_init_query_functions(struct r300_context* r300) {
- r300->context.create_query = r300_create_query;
- r300->context.destroy_query = r300_destroy_query;
- r300->context.begin_query = r300_begin_query;
- r300->context.end_query = r300_end_query;
- r300->context.get_query_result = r300_get_query_result;
- r300->context.render_condition = r300_render_condition;
+ if (DBG_ON(r300, DBG_FAKE_OCC)) {
+ r300->context.create_query = r300_fake_create_query;
+ r300->context.destroy_query = r300_fake_destroy_query;
+ r300->context.begin_query = r300_fake_begin_query;
+ r300->context.end_query = r300_fake_end_query;
+ r300->context.get_query_result = r300_fake_get_query_result;
+ r300->context.render_condition = r300_fake_render_condition;
+ } else {
+ r300->context.create_query = r300_create_query;
+ r300->context.destroy_query = r300_destroy_query;
+ r300->context.begin_query = r300_begin_query;
+ r300->context.end_query = r300_end_query;
+ r300->context.get_query_result = r300_get_query_result;
+ r300->context.render_condition = r300_render_condition;
+ }
}
diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h
index c4fa19ace5..180560175a 100644
--- a/src/gallium/drivers/r300/r300_reg.h
+++ b/src/gallium/drivers/r300/r300_reg.h
@@ -1630,6 +1630,40 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_TX_FORMAT_GAMMA (1 << 21)
# define R300_TX_FORMAT_YUV_TO_RGB (1 << 22)
+# define R300_TX_CACHE(x) ((x) << 27)
+# define R300_TX_CACHE_WHOLE 0
+/* reserved */
+# define R300_TX_CACHE_HALF_0 2
+# define R300_TX_CACHE_HALF_1 3
+# define R300_TX_CACHE_FOURTH_0 4
+# define R300_TX_CACHE_FOURTH_1 5
+# define R300_TX_CACHE_FOURTH_2 6
+# define R300_TX_CACHE_FOURTH_3 7
+# define R300_TX_CACHE_EIGHTH_0 8
+# define R300_TX_CACHE_EIGHTH_1 9
+# define R300_TX_CACHE_EIGHTH_2 10
+# define R300_TX_CACHE_EIGHTH_3 11
+# define R300_TX_CACHE_EIGHTH_4 12
+# define R300_TX_CACHE_EIGHTH_5 13
+# define R300_TX_CACHE_EIGHTH_6 14
+# define R300_TX_CACHE_EIGHTH_7 15
+# define R300_TX_CACHE_SIXTEENTH_0 16
+# define R300_TX_CACHE_SIXTEENTH_1 17
+# define R300_TX_CACHE_SIXTEENTH_2 18
+# define R300_TX_CACHE_SIXTEENTH_3 19
+# define R300_TX_CACHE_SIXTEENTH_4 20
+# define R300_TX_CACHE_SIXTEENTH_5 21
+# define R300_TX_CACHE_SIXTEENTH_6 22
+# define R300_TX_CACHE_SIXTEENTH_7 23
+# define R300_TX_CACHE_SIXTEENTH_8 24
+# define R300_TX_CACHE_SIXTEENTH_9 25
+# define R300_TX_CACHE_SIXTEENTH_10 26
+# define R300_TX_CACHE_SIXTEENTH_11 27
+# define R300_TX_CACHE_SIXTEENTH_12 28
+# define R300_TX_CACHE_SIXTEENTH_13 29
+# define R300_TX_CACHE_SIXTEENTH_14 30
+# define R300_TX_CACHE_SIXTEENTH_15 31
+
#define R300_TX_FORMAT2_0 0x4500 /* obvious missing in gap */
# define R300_TX_PITCHMASK_SHIFT 0
# define R300_TX_PITCHMASK_MASK (2047 << 0)
@@ -2639,6 +2673,24 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
/* Z Buffer Clear Value */
#define R300_ZB_DEPTHCLEARVALUE 0x4f28
+/* Z Mask RAM is a Z compression buffer.
+ * Each dword of the Z Mask contains compression info for 16 4x4 pixel blocks,
+ * that is 2 bits for each block.
+ * On chips with 2 Z pipes, every other dword maps to a different pipe.
+ */
+
+/* The dword offset into Z mask RAM (bits 18:4) */
+#define R300_ZB_ZMASK_OFFSET 0x4f30
+
+/* Z Mask Pitch. */
+#define R300_ZB_ZMASK_PITCH 0x4f34
+
+/* Access to Z Mask RAM in a manner similar to HiZ RAM.
+ * The indices are autoincrementing. */
+#define R300_ZB_ZMASK_WRINDEX 0x4f38
+#define R300_ZB_ZMASK_DWORD 0x4f3c
+#define R300_ZB_ZMASK_RDINDEX 0x4f40
+
/* Hierarchical Z Memory Offset */
#define R300_ZB_HIZ_OFFSET 0x4f44
@@ -3437,9 +3489,18 @@ enum {
# define RADEON_WAIT_3D_IDLECLEAN (1 << 17)
# define RADEON_WAIT_HOST_IDLECLEAN (1 << 18)
+#define R200_3D_DRAW_IMMD_2 0xC0003500
+
+#define RADEON_CP_PACKET0 0x0 /* XXX stolen from radeon_reg.h */
#define RADEON_CP_PACKET3 0xC0000000
-#define R200_3D_DRAW_IMMD_2 0xC0003500
+#define RADEON_ONE_REG_WR (1 << 15)
+
+#define CP_PACKET0(register, count) \
+ (RADEON_CP_PACKET0 | ((count) << 16) | ((register) >> 2))
+
+#define CP_PACKET3(op, count) \
+ (RADEON_CP_PACKET3 | (op) | ((count) << 16))
#endif /* _R300_REG_H */
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index 23caaa5473..53728431a6 100644
--- a/src/gallium/drivers/r300/r300_render.c
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -35,6 +35,7 @@
#include "util/u_prim.h"
#include "r300_cs.h"
+#include "r300_cb.h"
#include "r300_context.h"
#include "r300_screen_buffer.h"
#include "r300_emit.h"
@@ -43,6 +44,8 @@
#include <limits.h>
+#define IMMD_DWORDS 32
+
static uint32_t r300_translate_primitive(unsigned prim)
{
switch (prim) {
@@ -269,7 +272,7 @@ static boolean immd_is_good_idea(struct r300_context *r300,
return FALSE;
}
- if (count > 10) {
+ if (count * r300->velems->vertex_size_dwords > IMMD_DWORDS) {
return FALSE;
}
@@ -308,84 +311,75 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
struct pipe_vertex_element* velem;
struct pipe_vertex_buffer* vbuf;
unsigned vertex_element_count = r300->velems->count;
- unsigned i, v, vbi, dw, elem_offset, dwords;
+ unsigned i, v, vbi, dwords;
/* Size of the vertex, in dwords. */
- unsigned vertex_size = 0;
-
- /* Offsets of the attribute, in dwords, from the start of the vertex. */
- unsigned offset[PIPE_MAX_ATTRIBS];
+ unsigned vertex_size = r300->velems->vertex_size_dwords;
/* Size of the vertex element, in dwords. */
unsigned size[PIPE_MAX_ATTRIBS];
/* Stride to the same attrib in the next vertex in the vertex buffer,
* in dwords. */
- unsigned stride[PIPE_MAX_ATTRIBS] = {0};
+ unsigned stride[PIPE_MAX_ATTRIBS];
/* Mapped vertex buffers. */
- uint32_t* map[PIPE_MAX_ATTRIBS] = {0};
- struct pipe_transfer* transfer[PIPE_MAX_ATTRIBS] = {NULL};
+ uint32_t* map[PIPE_MAX_ATTRIBS];
+ uint32_t* mapelem[PIPE_MAX_ATTRIBS];
+ struct pipe_transfer* transfer[PIPE_MAX_ATTRIBS] = {0};
- CS_LOCALS(r300);
+ CB_LOCALS;
/* Calculate the vertex size, offsets, strides etc. and map the buffers. */
for (i = 0; i < vertex_element_count; i++) {
velem = &r300->velems->velem[i];
- offset[i] = velem->src_offset / 4;
- size[i] = util_format_get_blocksize(velem->src_format) / 4;
- vertex_size += size[i];
+ size[i] = r300->velems->hw_format_size[i] / 4;
vbi = velem->vertex_buffer_index;
+ vbuf = &r300->vertex_buffer[vbi];
+ stride[i] = vbuf->stride / 4;
/* Map the buffer. */
- if (!map[vbi]) {
- vbuf = &r300->vertex_buffer[vbi];
+ if (!transfer[vbi]) {
map[vbi] = (uint32_t*)pipe_buffer_map(&r300->context,
vbuf->buffer,
PIPE_TRANSFER_READ,
&transfer[vbi]);
- map[vbi] += vbuf->buffer_offset / 4;
- stride[vbi] = vbuf->stride / 4;
+ map[vbi] += (vbuf->buffer_offset / 4) + stride[i] * start;
}
+ mapelem[i] = map[vbi] + (velem->src_offset / 4);
}
dwords = 9 + count * vertex_size;
r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0, NULL);
- BEGIN_CS(dwords);
- OUT_CS_REG(R300_GA_COLOR_CONTROL,
+ BEGIN_CS_AS_CB(r300, dwords);
+ OUT_CB_REG(R300_GA_COLOR_CONTROL,
r300_provoking_vertex_fixes(r300, mode));
- OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size);
- OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
- OUT_CS(count - 1);
- OUT_CS(0);
- OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, count * vertex_size);
- OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) |
+ OUT_CB_REG(R300_VAP_VTX_SIZE, vertex_size);
+ OUT_CB_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
+ OUT_CB(count - 1);
+ OUT_CB(0);
+ OUT_CB_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, count * vertex_size);
+ OUT_CB(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) |
r300_translate_primitive(mode));
/* Emit vertices. */
for (v = 0; v < count; v++) {
for (i = 0; i < vertex_element_count; i++) {
- velem = &r300->velems->velem[i];
- vbi = velem->vertex_buffer_index;
- elem_offset = offset[i] + stride[vbi] * (v + start);
-
- for (dw = 0; dw < size[i]; dw++) {
- OUT_CS(map[vbi][elem_offset + dw]);
- }
+ OUT_CB_TABLE(&mapelem[i][stride[i] * v], size[i]);
}
}
- END_CS;
+ END_CB;
/* Unmap buffers. */
for (i = 0; i < vertex_element_count; i++) {
vbi = r300->velems->velem[i].vertex_buffer_index;
- if (map[vbi]) {
+ if (transfer[vbi]) {
vbuf = &r300->vertex_buffer[vbi];
pipe_buffer_unmap(&r300->context, vbuf->buffer, transfer[vbi]);
- map[vbi] = NULL;
+ transfer[vbi] = NULL;
}
}
}
@@ -482,111 +476,6 @@ static void r300_emit_draw_elements(struct r300_context *r300,
END_CS;
}
-static void r300_shorten_ubyte_elts(struct r300_context* r300,
- struct pipe_resource** elts,
- int index_bias,
- unsigned start,
- unsigned count)
-{
- struct pipe_context* context = &r300->context;
- struct pipe_screen* screen = r300->context.screen;
- struct pipe_resource* new_elts;
- unsigned char *in_map;
- unsigned short *out_map;
- struct pipe_transfer *src_transfer, *dst_transfer;
- unsigned i;
-
- new_elts = pipe_buffer_create(screen,
- PIPE_BIND_INDEX_BUFFER,
- 2 * count);
-
- in_map = pipe_buffer_map(context, *elts, PIPE_TRANSFER_READ, &src_transfer);
- out_map = pipe_buffer_map(context, new_elts, PIPE_TRANSFER_WRITE, &dst_transfer);
-
- in_map += start;
-
- for (i = 0; i < count; i++) {
- *out_map = (unsigned short)(*in_map + index_bias);
- in_map++;
- out_map++;
- }
-
- pipe_buffer_unmap(context, *elts, src_transfer);
- pipe_buffer_unmap(context, new_elts, dst_transfer);
-
- *elts = new_elts;
-}
-
-static void r300_rebuild_ushort_elts(struct r300_context *r300,
- struct pipe_resource **elts,
- int index_bias,
- unsigned start, unsigned count)
-{
- struct pipe_context *context = &r300->context;
- struct pipe_transfer *in_transfer = NULL;
- struct pipe_transfer *out_transfer = NULL;
- struct pipe_resource *new_elts;
- unsigned short *in_map;
- unsigned short *out_map;
- unsigned i;
-
- new_elts = pipe_buffer_create(context->screen,
- PIPE_BIND_INDEX_BUFFER,
- 2 * count);
-
- in_map = pipe_buffer_map(context, *elts,
- PIPE_TRANSFER_READ, &in_transfer);
- out_map = pipe_buffer_map(context, new_elts,
- PIPE_TRANSFER_WRITE, &out_transfer);
-
- in_map += start;
- for (i = 0; i < count; i++) {
- *out_map = (unsigned short)(*in_map + index_bias);
- in_map++;
- out_map++;
- }
-
- pipe_buffer_unmap(context, *elts, in_transfer);
- pipe_buffer_unmap(context, new_elts, out_transfer);
-
- *elts = new_elts;
-}
-
-static void r300_rebuild_uint_elts(struct r300_context *r300,
- struct pipe_resource **elts,
- int index_bias,
- unsigned start, unsigned count)
-{
- struct pipe_context *context = &r300->context;
- struct pipe_transfer *in_transfer = NULL;
- struct pipe_transfer *out_transfer = NULL;
- struct pipe_resource *new_elts;
- unsigned int *in_map;
- unsigned int *out_map;
- unsigned i;
-
- new_elts = pipe_buffer_create(context->screen,
- PIPE_BIND_INDEX_BUFFER,
- 2 * count);
-
- in_map = pipe_buffer_map(context, *elts,
- PIPE_TRANSFER_READ, &in_transfer);
- out_map = pipe_buffer_map(context, new_elts,
- PIPE_TRANSFER_WRITE, &out_transfer);
-
- in_map += start;
- for (i = 0; i < count; i++) {
- *out_map = (unsigned int)(*in_map + index_bias);
- in_map++;
- out_map++;
- }
-
- pipe_buffer_unmap(context, *elts, in_transfer);
- pipe_buffer_unmap(context, new_elts, out_transfer);
-
- *elts = new_elts;
-}
-
/* This is the fast-path drawing & emission for HW TCL. */
static void r300_draw_range_elements(struct pipe_context* pipe,
struct pipe_resource* indexBuffer,
@@ -605,6 +494,7 @@ static void r300_draw_range_elements(struct pipe_context* pipe,
r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0);
unsigned short_count;
int buffer_offset = 0, index_offset = 0; /* for index bias emulation */
+ boolean translate = FALSE;
if (r300->skip_rendering) {
return;
@@ -614,33 +504,25 @@ static void r300_draw_range_elements(struct pipe_context* pipe,
return;
}
- if (indexBias && !index_bias_supported(r300)) {
- r300_split_index_bias(r300, indexBias, &buffer_offset, &index_offset);
+ /* Index buffer range checking. */
+ if ((start + count) * indexSize > indexBuffer->width0) {
+ fprintf(stderr, "r300: Invalid index buffer range. Skipping rendering.\n");
+ return;
}
- /* Rebuild the index buffer if needed. */
- switch (indexSize) {
- case 1:
- r300_shorten_ubyte_elts(r300, &indexBuffer, index_offset, start, count);
- indexSize = 2;
- start = 0;
- break;
-
- case 2:
- if (start % 2 != 0 || index_offset) {
- r300_rebuild_ushort_elts(r300, &indexBuffer, index_offset, start, count);
- start = 0;
- }
- break;
+ /* Set up fallback for incompatible vertex layout if needed. */
+ if (r300->incompatible_vb_layout || r300->velems->incompatible_layout) {
+ r300_begin_vertex_translate(r300);
+ translate = TRUE;
+ }
- case 4:
- if (index_offset) {
- r300_rebuild_uint_elts(r300, &indexBuffer, index_offset, start, count);
- start = 0;
- }
- break;
+ if (indexBias && !index_bias_supported(r300)) {
+ r300_split_index_bias(r300, indexBias, &buffer_offset, &index_offset);
}
+ r300_translate_index_buffer(r300, &indexBuffer, &indexSize, index_offset,
+ &start, count);
+
r300_update_derived_state(r300);
r300_upload_index_buffer(r300, &indexBuffer, indexSize, start, count);
@@ -676,6 +558,10 @@ static void r300_draw_range_elements(struct pipe_context* pipe,
if (indexBuffer != orgIndexBuffer) {
pipe_resource_reference( &indexBuffer, NULL );
}
+
+ if (translate) {
+ r300_end_vertex_translate(r300);
+ }
}
/* Simple helpers for context setup. Should probably be moved to util. */
@@ -699,6 +585,7 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
count > 65536 &&
r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0);
unsigned short_count;
+ boolean translate = FALSE;
if (r300->skip_rendering) {
return;
@@ -708,6 +595,12 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
return;
}
+ /* Set up fallback for incompatible vertex layout if needed. */
+ if (r300->incompatible_vb_layout || r300->velems->incompatible_layout) {
+ r300_begin_vertex_translate(r300);
+ translate = TRUE;
+ }
+
r300_update_derived_state(r300);
if (immd_is_good_idea(r300, count)) {
@@ -737,6 +630,10 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
}
u_upload_flush(r300->upload_vb);
}
+
+ if (translate) {
+ r300_end_vertex_translate(r300);
+ }
}
/****************************************************************************
@@ -1016,7 +913,7 @@ static void r300_render_draw_elements(struct vbuf_render* render,
unsigned max_index = (r300render->vbo_size - r300render->vbo_offset) /
(r300render->r300->vertex_info.size * 4) - 1;
unsigned short_count;
- struct r300_cs_info cs_info;
+ unsigned free_dwords;
CS_LOCALS(r300);
@@ -1029,9 +926,9 @@ static void r300_render_draw_elements(struct vbuf_render* render,
NULL, 256, 0, 0, &end_cs_dwords);
while (count) {
- r300->rws->get_cs_info(r300->rws, &cs_info);
+ free_dwords = r300->rws->get_cs_free_dwords(r300->rws);
- short_count = MIN2(count, (cs_info.free - end_cs_dwords - 6) * 2);
+ short_count = MIN2(count, (free_dwords - end_cs_dwords - 6) * 2);
BEGIN_CS(6 + (short_count+1)/2);
OUT_CS_REG(R300_GA_COLOR_CONTROL,
@@ -1117,132 +1014,45 @@ struct draw_stage* r300_draw_stage(struct r300_context* r300)
}
/****************************************************************************
- * Two-sided stencil reference value fallback. It's designed to be as much
- * separate from rest of the driver as possible.
+ * End of SW TCL functions *
***************************************************************************/
-struct r300_stencilref_context {
- void (*draw_arrays)(struct pipe_context *pipe,
- unsigned mode, unsigned start, unsigned count);
-
- void (*draw_range_elements)(
- struct pipe_context *pipe, struct pipe_resource *indexBuffer,
- unsigned indexSize, int indexBias, unsigned minIndex, unsigned maxIndex,
- unsigned mode, unsigned start, unsigned count);
-
- uint32_t rs_cull_mode;
- uint32_t zb_stencilrefmask;
- ubyte ref_value_front;
-};
-
-static boolean r300_stencilref_needed(struct r300_context *r300)
+static void r300_resource_resolve(struct pipe_context* pipe,
+ struct pipe_resource* dest,
+ struct pipe_subresource subdest,
+ struct pipe_resource* src,
+ struct pipe_subresource subsrc)
{
- struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state;
-
- return dsa->two_sided_stencil_ref ||
- (dsa->two_sided &&
- r300->stencil_ref.ref_value[0] != r300->stencil_ref.ref_value[1]);
-}
-
-/* Set drawing for front faces. */
-static void r300_stencilref_begin(struct r300_context *r300)
-{
- struct r300_stencilref_context *sr = r300->stencilref_fallback;
- struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state;
- struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state;
-
- /* Save state. */
- sr->rs_cull_mode = rs->cull_mode;
- sr->zb_stencilrefmask = dsa->stencil_ref_mask;
- sr->ref_value_front = r300->stencil_ref.ref_value[0];
-
- /* We *cull* pixels, therefore no need to mask out the bits. */
- rs->cull_mode |= R300_CULL_BACK;
-
- r300->rs_state.dirty = TRUE;
-}
-
-/* Set drawing for back faces. */
-static void r300_stencilref_switch_side(struct r300_context *r300)
-{
- struct r300_stencilref_context *sr = r300->stencilref_fallback;
- struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state;
- struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state;
-
- rs->cull_mode = sr->rs_cull_mode | R300_CULL_FRONT;
- dsa->stencil_ref_mask = dsa->stencil_ref_bf;
- r300->stencil_ref.ref_value[0] = r300->stencil_ref.ref_value[1];
-
- r300->rs_state.dirty = TRUE;
- r300->dsa_state.dirty = TRUE;
-}
-
-/* Restore the original state. */
-static void r300_stencilref_end(struct r300_context *r300)
-{
- struct r300_stencilref_context *sr = r300->stencilref_fallback;
- struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state;
- struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state;
-
- /* Restore state. */
- rs->cull_mode = sr->rs_cull_mode;
- dsa->stencil_ref_mask = sr->zb_stencilrefmask;
- r300->stencil_ref.ref_value[0] = sr->ref_value_front;
-
- r300->rs_state.dirty = TRUE;
- r300->dsa_state.dirty = TRUE;
-}
-
-static void r300_stencilref_draw_arrays(struct pipe_context *pipe, unsigned mode,
- unsigned start, unsigned count)
-{
- struct r300_context *r300 = r300_context(pipe);
- struct r300_stencilref_context *sr = r300->stencilref_fallback;
-
- if (!r300_stencilref_needed(r300)) {
- sr->draw_arrays(pipe, mode, start, count);
- } else {
- r300_stencilref_begin(r300);
- sr->draw_arrays(pipe, mode, start, count);
- r300_stencilref_switch_side(r300);
- sr->draw_arrays(pipe, mode, start, count);
- r300_stencilref_end(r300);
- }
-}
-
-static void r300_stencilref_draw_range_elements(
- struct pipe_context *pipe, struct pipe_resource *indexBuffer,
- unsigned indexSize, int indexBias, unsigned minIndex, unsigned maxIndex,
- unsigned mode, unsigned start, unsigned count)
-{
- struct r300_context *r300 = r300_context(pipe);
- struct r300_stencilref_context *sr = r300->stencilref_fallback;
-
- if (!r300_stencilref_needed(r300)) {
- sr->draw_range_elements(pipe, indexBuffer, indexSize, indexBias,
- minIndex, maxIndex, mode, start, count);
- } else {
- r300_stencilref_begin(r300);
- sr->draw_range_elements(pipe, indexBuffer, indexSize, indexBias,
- minIndex, maxIndex, mode, start, count);
- r300_stencilref_switch_side(r300);
- sr->draw_range_elements(pipe, indexBuffer, indexSize, indexBias,
- minIndex, maxIndex, mode, start, count);
- r300_stencilref_end(r300);
- }
-}
-
-static void r300_plug_in_stencil_ref_fallback(struct r300_context *r300)
-{
- r300->stencilref_fallback = CALLOC_STRUCT(r300_stencilref_context);
-
- /* Save original draw functions. */
- r300->stencilref_fallback->draw_arrays = r300->context.draw_arrays;
- r300->stencilref_fallback->draw_range_elements = r300->context.draw_range_elements;
-
- /* Override the draw functions. */
- r300->context.draw_arrays = r300_stencilref_draw_arrays;
- r300->context.draw_range_elements = r300_stencilref_draw_range_elements;
+ struct r300_context* r300 = r300_context(pipe);
+ struct r300_aa_state *aa = (struct r300_aa_state*)r300->aa_state.state;
+ struct pipe_surface* srcsurf = src->screen->get_tex_surface(src->screen,
+ src, subsrc.face, subsrc.level, 0, 0);
+ float color[] = {0, 0, 0, 0};
+
+ DBG(r300, DBG_DRAW, "r300: Resolving resource...\n");
+
+ /* Enable AA resolve. */
+ aa->dest = r300_surface(
+ dest->screen->get_tex_surface(dest->screen, dest, subdest.face,
+ subdest.level, 0, 0));
+
+ aa->aaresolve_ctl =
+ R300_RB3D_AARESOLVE_CTL_AARESOLVE_MODE_RESOLVE |
+ R300_RB3D_AARESOLVE_CTL_AARESOLVE_ALPHA_AVERAGE;
+ r300->aa_state.size = 12;
+ r300->aa_state.dirty = TRUE;
+
+ /* Resolve the surface. */
+ r300->context.clear_render_target(pipe,
+ srcsurf, color, 0, 0, src->width0, src->height0);
+
+ /* Disable AA resolve. */
+ aa->aaresolve_ctl = 0;
+ r300->aa_state.size = 4;
+ r300->aa_state.dirty = TRUE;
+
+ pipe_surface_reference((struct pipe_surface**)&srcsurf, NULL);
+ pipe_surface_reference((struct pipe_surface**)&aa->dest, NULL);
}
void r300_init_render_functions(struct r300_context *r300)
@@ -1259,7 +1069,9 @@ void r300_init_render_functions(struct r300_context *r300)
r300->context.draw_range_elements = r300_swtcl_draw_range_elements;
}
- /* Plug in two-sided stencil reference value fallback if needed. */
+ r300->context.resource_resolve = r300_resource_resolve;
+
+ /* Plug in the two-sided stencil reference value fallback if needed. */
if (!r300->screen->caps.is_r500)
r300_plug_in_stencil_ref_fallback(r300);
}
diff --git a/src/gallium/drivers/r300/r300_render_stencilref.c b/src/gallium/drivers/r300/r300_render_stencilref.c
new file mode 100644
index 0000000000..9a6b4e12ff
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_render_stencilref.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2010 Marek Olšák <maraeo@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/**
+ * The two-sided stencil reference value fallback for r3xx-r4xx chips.
+ * These chips support two-sided stencil functions but they do not support
+ * a two-sided reference value.
+ *
+ * The functions below split every draw call which uses the two-sided
+ * reference value into two draw calls -- the first one renders front faces
+ * and the second renders back faces with the other reference value.
+ */
+
+#include "r300_context.h"
+#include "r300_reg.h"
+
+struct r300_stencilref_context {
+ void (*draw_arrays)(struct pipe_context *pipe,
+ unsigned mode, unsigned start, unsigned count);
+
+ void (*draw_range_elements)(
+ struct pipe_context *pipe, struct pipe_resource *indexBuffer,
+ unsigned indexSize, int indexBias, unsigned minIndex, unsigned maxIndex,
+ unsigned mode, unsigned start, unsigned count);
+
+ uint32_t rs_cull_mode;
+ uint32_t zb_stencilrefmask;
+ ubyte ref_value_front;
+};
+
+static boolean r300_stencilref_needed(struct r300_context *r300)
+{
+ struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state;
+
+ return dsa->two_sided_stencil_ref ||
+ (dsa->two_sided &&
+ r300->stencil_ref.ref_value[0] != r300->stencil_ref.ref_value[1]);
+}
+
+/* Set drawing for front faces. */
+static void r300_stencilref_begin(struct r300_context *r300)
+{
+ struct r300_stencilref_context *sr = r300->stencilref_fallback;
+ struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state;
+ struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state;
+
+ /* Save state. */
+ sr->rs_cull_mode = rs->cb_main[rs->cull_mode_index];
+ sr->zb_stencilrefmask = dsa->stencil_ref_mask;
+ sr->ref_value_front = r300->stencil_ref.ref_value[0];
+
+ /* We *cull* pixels, therefore no need to mask out the bits. */
+ rs->cb_main[rs->cull_mode_index] |= R300_CULL_BACK;
+
+ r300->rs_state.dirty = TRUE;
+}
+
+/* Set drawing for back faces. */
+static void r300_stencilref_switch_side(struct r300_context *r300)
+{
+ struct r300_stencilref_context *sr = r300->stencilref_fallback;
+ struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state;
+ struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state;
+
+ rs->cb_main[rs->cull_mode_index] = sr->rs_cull_mode | R300_CULL_FRONT;
+ dsa->stencil_ref_mask = dsa->stencil_ref_bf;
+ r300->stencil_ref.ref_value[0] = r300->stencil_ref.ref_value[1];
+
+ r300->rs_state.dirty = TRUE;
+ r300->dsa_state.dirty = TRUE;
+}
+
+/* Restore the original state. */
+static void r300_stencilref_end(struct r300_context *r300)
+{
+ struct r300_stencilref_context *sr = r300->stencilref_fallback;
+ struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state;
+ struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state;
+
+ /* Restore state. */
+ rs->cb_main[rs->cull_mode_index] = sr->rs_cull_mode;
+ dsa->stencil_ref_mask = sr->zb_stencilrefmask;
+ r300->stencil_ref.ref_value[0] = sr->ref_value_front;
+
+ r300->rs_state.dirty = TRUE;
+ r300->dsa_state.dirty = TRUE;
+}
+
+static void r300_stencilref_draw_arrays(struct pipe_context *pipe, unsigned mode,
+ unsigned start, unsigned count)
+{
+ struct r300_context *r300 = r300_context(pipe);
+ struct r300_stencilref_context *sr = r300->stencilref_fallback;
+
+ if (!r300_stencilref_needed(r300)) {
+ sr->draw_arrays(pipe, mode, start, count);
+ } else {
+ r300_stencilref_begin(r300);
+ sr->draw_arrays(pipe, mode, start, count);
+ r300_stencilref_switch_side(r300);
+ sr->draw_arrays(pipe, mode, start, count);
+ r300_stencilref_end(r300);
+ }
+}
+
+static void r300_stencilref_draw_range_elements(
+ struct pipe_context *pipe, struct pipe_resource *indexBuffer,
+ unsigned indexSize, int indexBias, unsigned minIndex, unsigned maxIndex,
+ unsigned mode, unsigned start, unsigned count)
+{
+ struct r300_context *r300 = r300_context(pipe);
+ struct r300_stencilref_context *sr = r300->stencilref_fallback;
+
+ if (!r300_stencilref_needed(r300)) {
+ sr->draw_range_elements(pipe, indexBuffer, indexSize, indexBias,
+ minIndex, maxIndex, mode, start, count);
+ } else {
+ r300_stencilref_begin(r300);
+ sr->draw_range_elements(pipe, indexBuffer, indexSize, indexBias,
+ minIndex, maxIndex, mode, start, count);
+ r300_stencilref_switch_side(r300);
+ sr->draw_range_elements(pipe, indexBuffer, indexSize, indexBias,
+ minIndex, maxIndex, mode, start, count);
+ r300_stencilref_end(r300);
+ }
+}
+
+void r300_plug_in_stencil_ref_fallback(struct r300_context *r300)
+{
+ r300->stencilref_fallback = CALLOC_STRUCT(r300_stencilref_context);
+
+ /* Save original draw functions. */
+ r300->stencilref_fallback->draw_arrays = r300->context.draw_arrays;
+ r300->stencilref_fallback->draw_range_elements = r300->context.draw_range_elements;
+
+ /* Override the draw functions. */
+ r300->context.draw_arrays = r300_stencilref_draw_arrays;
+ r300->context.draw_range_elements = r300_stencilref_draw_range_elements;
+}
diff --git a/src/gallium/drivers/r300/r300_render_translate.c b/src/gallium/drivers/r300/r300_render_translate.c
new file mode 100644
index 0000000000..0ea11e5bfc
--- /dev/null
+++ b/src/gallium/drivers/r300/r300_render_translate.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright 2010 Marek Olšák <maraeo@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+/**
+ * The functions below translate vertex and index buffers to the layout
+ * compatible with the hardware, so that all vertex and index fetches are
+ * DWORD-aligned and all used vertex and index formats are supported.
+ * For indices, an optional index offset is added to each index.
+ */
+
+#include "r300_context.h"
+#include "translate/translate.h"
+
+void r300_begin_vertex_translate(struct r300_context *r300)
+{
+ struct pipe_context *pipe = &r300->context;
+ struct translate_key key = {0};
+ struct translate_element *te;
+ unsigned tr_elem_index[PIPE_MAX_ATTRIBS] = {0};
+ struct translate *tr;
+ struct r300_vertex_element_state *ve = r300->velems;
+ boolean vb_translated[PIPE_MAX_ATTRIBS] = {0};
+ void *vb_map[PIPE_MAX_ATTRIBS] = {0}, *out_map;
+ struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0}, *out_transfer;
+ struct pipe_resource *out_buffer;
+ unsigned i, num_verts;
+
+ /* Initialize the translate key, i.e. the recipe how vertices should be
+ * translated. */
+ for (i = 0; i < ve->count; i++) {
+ struct pipe_vertex_buffer *vb =
+ &r300->vertex_buffer[ve->velem[i].vertex_buffer_index];
+ enum pipe_format output_format = ve->hw_format[i];
+ unsigned output_format_size = ve->hw_format_size[i];
+
+ /* Check for support. */
+ if (ve->velem[i].src_format == ve->hw_format[i] &&
+ (vb->buffer_offset + ve->velem[i].src_offset) % 4 == 0 &&
+ vb->stride % 4 == 0) {
+ continue;
+ }
+
+ /* Workaround for translate: output floats instead of halfs. */
+ switch (output_format) {
+ case PIPE_FORMAT_R16_FLOAT:
+ output_format = PIPE_FORMAT_R32_FLOAT;
+ output_format_size = 4;
+ break;
+ case PIPE_FORMAT_R16G16_FLOAT:
+ output_format = PIPE_FORMAT_R32G32_FLOAT;
+ output_format_size = 8;
+ break;
+ case PIPE_FORMAT_R16G16B16_FLOAT:
+ output_format = PIPE_FORMAT_R32G32B32_FLOAT;
+ output_format_size = 12;
+ break;
+ case PIPE_FORMAT_R16G16B16A16_FLOAT:
+ output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ output_format_size = 16;
+ break;
+ default:;
+ }
+
+ /* Add this vertex element. */
+ te = &key.element[key.nr_elements];
+ /*te->type;
+ te->instance_divisor;*/
+ te->input_buffer = ve->velem[i].vertex_buffer_index;
+ te->input_format = ve->velem[i].src_format;
+ te->input_offset = vb->buffer_offset + ve->velem[i].src_offset;
+ te->output_format = output_format;
+ te->output_offset = key.output_stride;
+
+ key.output_stride += output_format_size;
+ vb_translated[ve->velem[i].vertex_buffer_index] = TRUE;
+ tr_elem_index[i] = key.nr_elements;
+ key.nr_elements++;
+ }
+
+ /* Get a translate object. */
+ tr = translate_cache_find(r300->tran.translate_cache, &key);
+
+ /* Map buffers we want to translate. */
+ for (i = 0; i < r300->vertex_buffer_count; i++) {
+ if (vb_translated[i]) {
+ struct pipe_vertex_buffer *vb = &r300->vertex_buffer[i];
+
+ vb_map[i] = pipe_buffer_map(pipe, vb->buffer,
+ PIPE_TRANSFER_READ, &vb_transfer[i]);
+
+ tr->set_buffer(tr, i, vb_map[i], vb->stride, vb->max_index);
+ }
+ }
+
+ /* Create and map the output buffer. */
+ num_verts = r300->vertex_buffer_max_index + 1;
+
+ out_buffer = pipe_buffer_create(&r300->screen->screen,
+ PIPE_BIND_VERTEX_BUFFER,
+ key.output_stride * num_verts);
+
+ out_map = pipe_buffer_map(pipe, out_buffer, PIPE_TRANSFER_WRITE,
+ &out_transfer);
+
+ /* Translate. */
+ tr->run(tr, 0, num_verts, 0, out_map);
+
+ /* Unmap all buffers. */
+ for (i = 0; i < r300->vertex_buffer_count; i++) {
+ if (vb_translated[i]) {
+ pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer,
+ vb_transfer[i]);
+ }
+ }
+
+ pipe_buffer_unmap(pipe, out_buffer, out_transfer);
+
+ /* Setup the new vertex buffer in the first free slot. */
+ for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
+ struct pipe_vertex_buffer *vb = &r300->vertex_buffer[i];
+
+ if (!vb->buffer) {
+ pipe_resource_reference(&vb->buffer, out_buffer);
+ vb->buffer_offset = 0;
+ vb->max_index = num_verts - 1;
+ vb->stride = key.output_stride;
+ r300->tran.vb_slot = i;
+ break;
+ }
+ }
+
+ /* Save and replace vertex elements. */
+ {
+ struct pipe_vertex_element new_velems[PIPE_MAX_ATTRIBS];
+
+ r300->tran.saved_velems = r300->velems;
+
+ for (i = 0; i < ve->count; i++) {
+ if (vb_translated[ve->velem[i].vertex_buffer_index]) {
+ te = &key.element[tr_elem_index[i]];
+ new_velems[i].instance_divisor = ve->velem[i].instance_divisor;
+ new_velems[i].src_format = te->output_format;
+ new_velems[i].src_offset = te->output_offset;
+ new_velems[i].vertex_buffer_index = r300->tran.vb_slot;
+ } else {
+ memcpy(&new_velems[i], &ve->velem[i],
+ sizeof(struct pipe_vertex_element));
+ }
+ }
+
+ r300->tran.new_velems =
+ pipe->create_vertex_elements_state(pipe, ve->count, new_velems);
+ pipe->bind_vertex_elements_state(pipe, r300->tran.new_velems);
+ }
+
+ pipe_resource_reference(&out_buffer, NULL);
+}
+
+void r300_end_vertex_translate(struct r300_context *r300)
+{
+ struct pipe_context *pipe = &r300->context;
+
+ /* Restore vertex elements. */
+ pipe->bind_vertex_elements_state(pipe, r300->tran.saved_velems);
+ pipe->delete_vertex_elements_state(pipe, r300->tran.new_velems);
+
+ /* Delete the now-unused VBO. */
+ pipe_resource_reference(&r300->vertex_buffer[r300->tran.vb_slot].buffer,
+ NULL);
+}
+
+static void r300_shorten_ubyte_elts(struct r300_context* r300,
+ struct pipe_resource** elts,
+ int index_bias,
+ unsigned start,
+ unsigned count)
+{
+ struct pipe_context* context = &r300->context;
+ struct pipe_screen* screen = r300->context.screen;
+ struct pipe_resource* new_elts;
+ unsigned char *in_map;
+ unsigned short *out_map;
+ struct pipe_transfer *src_transfer, *dst_transfer;
+ unsigned i;
+
+ new_elts = pipe_buffer_create(screen,
+ PIPE_BIND_INDEX_BUFFER,
+ 2 * count);
+
+ in_map = pipe_buffer_map(context, *elts, PIPE_TRANSFER_READ, &src_transfer);
+ out_map = pipe_buffer_map(context, new_elts, PIPE_TRANSFER_WRITE, &dst_transfer);
+
+ in_map += start;
+
+ for (i = 0; i < count; i++) {
+ *out_map = (unsigned short)(*in_map + index_bias);
+ in_map++;
+ out_map++;
+ }
+
+ pipe_buffer_unmap(context, *elts, src_transfer);
+ pipe_buffer_unmap(context, new_elts, dst_transfer);
+
+ *elts = new_elts;
+}
+
+static void r300_rebuild_ushort_elts(struct r300_context *r300,
+ struct pipe_resource **elts,
+ int index_bias,
+ unsigned start, unsigned count)
+{
+ struct pipe_context *context = &r300->context;
+ struct pipe_transfer *in_transfer = NULL;
+ struct pipe_transfer *out_transfer = NULL;
+ struct pipe_resource *new_elts;
+ unsigned short *in_map;
+ unsigned short *out_map;
+ unsigned i;
+
+ new_elts = pipe_buffer_create(context->screen,
+ PIPE_BIND_INDEX_BUFFER,
+ 2 * count);
+
+ in_map = pipe_buffer_map(context, *elts,
+ PIPE_TRANSFER_READ, &in_transfer);
+ out_map = pipe_buffer_map(context, new_elts,
+ PIPE_TRANSFER_WRITE, &out_transfer);
+
+ in_map += start;
+ for (i = 0; i < count; i++) {
+ *out_map = (unsigned short)(*in_map + index_bias);
+ in_map++;
+ out_map++;
+ }
+
+ pipe_buffer_unmap(context, *elts, in_transfer);
+ pipe_buffer_unmap(context, new_elts, out_transfer);
+
+ *elts = new_elts;
+}
+
+static void r300_rebuild_uint_elts(struct r300_context *r300,
+ struct pipe_resource **elts,
+ int index_bias,
+ unsigned start, unsigned count)
+{
+ struct pipe_context *context = &r300->context;
+ struct pipe_transfer *in_transfer = NULL;
+ struct pipe_transfer *out_transfer = NULL;
+ struct pipe_resource *new_elts;
+ unsigned int *in_map;
+ unsigned int *out_map;
+ unsigned i;
+
+ new_elts = pipe_buffer_create(context->screen,
+ PIPE_BIND_INDEX_BUFFER,
+ 2 * count);
+
+ in_map = pipe_buffer_map(context, *elts,
+ PIPE_TRANSFER_READ, &in_transfer);
+ out_map = pipe_buffer_map(context, new_elts,
+ PIPE_TRANSFER_WRITE, &out_transfer);
+
+ in_map += start;
+ for (i = 0; i < count; i++) {
+ *out_map = (unsigned int)(*in_map + index_bias);
+ in_map++;
+ out_map++;
+ }
+
+ pipe_buffer_unmap(context, *elts, in_transfer);
+ pipe_buffer_unmap(context, new_elts, out_transfer);
+
+ *elts = new_elts;
+}
+
+void r300_translate_index_buffer(struct r300_context *r300,
+ struct pipe_resource **index_buffer,
+ unsigned *index_size, unsigned index_offset,
+ unsigned *start, unsigned count)
+{
+ switch (*index_size) {
+ case 1:
+ r300_shorten_ubyte_elts(r300, index_buffer, index_offset, *start, count);
+ *index_size = 2;
+ *start = 0;
+ break;
+
+ case 2:
+ if (*start % 2 != 0 || index_offset) {
+ r300_rebuild_ushort_elts(r300, index_buffer, index_offset, *start, count);
+ *start = 0;
+ }
+ break;
+
+ case 4:
+ if (index_offset) {
+ r300_rebuild_uint_elts(r300, index_buffer, index_offset, *start, count);
+ *start = 0;
+ }
+ break;
+ }
+}
diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c
index fd522b84e1..5bba55906c 100644
--- a/src/gallium/drivers/r300/r300_screen.c
+++ b/src/gallium/drivers/r300/r300_screen.c
@@ -270,15 +270,24 @@ static boolean r300_is_format_supported(struct pipe_screen* screen,
format == PIPE_FORMAT_R16G16B16_FLOAT ||
format == PIPE_FORMAT_R16G16B16A16_FLOAT;
- if (target >= PIPE_MAX_TEXTURE_TYPES) {
- fprintf(stderr, "r300: Implementation error: Received bogus texture "
- "target %d in %s\n", target, __FUNCTION__);
- return FALSE;
+ switch (sample_count) {
+ case 0:
+ case 1:
+ break;
+ case 2:
+ case 3:
+ case 4:
+ case 6:
+ if (usage != PIPE_BIND_RENDER_TARGET ||
+ !util_format_is_rgba8_variant(
+ util_format_description(format))) {
+ return FALSE;
+ }
+ break;
+ default:
+ return FALSE;
}
- if (sample_count > 1)
- return FALSE;
-
/* Check sampler format support. */
if ((usage & PIPE_BIND_SAMPLER_VIEW) &&
/* Z24 cannot be sampled from on non-r5xx. */
@@ -320,6 +329,12 @@ static boolean r300_is_format_supported(struct pipe_screen* screen,
retval |= PIPE_BIND_VERTEX_BUFFER;
}
+ /* Transfers are always supported. */
+ if (usage & PIPE_BIND_TRANSFER_READ)
+ retval |= PIPE_BIND_TRANSFER_READ;
+ if (usage & PIPE_BIND_TRANSFER_WRITE)
+ retval |= PIPE_BIND_TRANSFER_WRITE;
+
return retval == usage;
}
diff --git a/src/gallium/drivers/r300/r300_screen.h b/src/gallium/drivers/r300/r300_screen.h
index 29492024fe..29cd5dbe26 100644
--- a/src/gallium/drivers/r300/r300_screen.h
+++ b/src/gallium/drivers/r300/r300_screen.h
@@ -65,7 +65,7 @@ static INLINE struct r300_screen* r300_screen(struct pipe_screen* screen) {
/* Logging. */
#define DBG_FP (1 << 1)
#define DBG_VP (1 << 2)
-#define DBG_CS (1 << 3)
+/* The bit (1 << 3) is unused. */
#define DBG_DRAW (1 << 4)
#define DBG_TEX (1 << 5)
#define DBG_TEXALLOC (1 << 6)
@@ -76,6 +76,7 @@ static INLINE struct r300_screen* r300_screen(struct pipe_screen* screen) {
#define DBG_ANISOHQ (1 << 16)
#define DBG_NO_TILING (1 << 17)
#define DBG_NO_IMMD (1 << 18)
+#define DBG_FAKE_OCC (1 << 19)
/* Statistics. */
#define DBG_STATS (1 << 24)
/*@}*/
diff --git a/src/gallium/drivers/r300/r300_screen_buffer.c b/src/gallium/drivers/r300/r300_screen_buffer.c
index 44179f19ed..7959e6a2f9 100644
--- a/src/gallium/drivers/r300/r300_screen_buffer.c
+++ b/src/gallium/drivers/r300/r300_screen_buffer.c
@@ -93,25 +93,28 @@ int r300_upload_user_buffers(struct r300_context *r300)
enum pipe_error ret = PIPE_OK;
int i, nr;
- nr = r300->vertex_buffer_count;
+ nr = r300->velems->count;
for (i = 0; i < nr; i++) {
- if (r300_buffer_is_user_buffer(r300->vertex_buffer[i].buffer)) {
- struct pipe_resource *upload_buffer = NULL;
- unsigned offset = 0; /*r300->vertex_buffer[i].buffer_offset * 4;*/
- unsigned size = r300->vertex_buffer[i].buffer->width0;
- unsigned upload_offset;
- ret = u_upload_buffer(r300->upload_vb,
- offset, size,
- r300->vertex_buffer[i].buffer,
- &upload_offset, &upload_buffer);
- if (ret)
- return ret;
-
- pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL);
- r300->vertex_buffer[i].buffer = upload_buffer;
- r300->vertex_buffer[i].buffer_offset = upload_offset;
- }
+ struct pipe_vertex_buffer *vb =
+ &r300->vertex_buffer[r300->velems->velem[i].vertex_buffer_index];
+
+ if (r300_buffer_is_user_buffer(vb->buffer)) {
+ struct pipe_resource *upload_buffer = NULL;
+ unsigned offset = 0; /*vb->buffer_offset * 4;*/
+ unsigned size = vb->buffer->width0;
+ unsigned upload_offset;
+ ret = u_upload_buffer(r300->upload_vb,
+ offset, size,
+ vb->buffer,
+ &upload_offset, &upload_buffer);
+ if (ret)
+ return ret;
+
+ pipe_resource_reference(&vb->buffer, NULL);
+ vb->buffer = upload_buffer;
+ vb->buffer_offset = upload_offset;
+ }
}
return ret;
}
@@ -261,10 +264,6 @@ struct pipe_resource *r300_buffer_create(struct pipe_screen *screen,
rbuf->b.vtbl = &r300_buffer_vtbl;
pipe_reference_init(&rbuf->b.b.reference, 1);
rbuf->b.b.screen = screen;
-
- if (rbuf->b.b.bind & R300_BIND_OQBO)
- alignment = 4096;
-
rbuf->domain = R300_DOMAIN_GTT;
rbuf->buf = r300screen->rws->buffer_create(r300screen->rws,
diff --git a/src/gallium/drivers/r300/r300_screen_buffer.h b/src/gallium/drivers/r300/r300_screen_buffer.h
index 87b42b9412..ff35585870 100644
--- a/src/gallium/drivers/r300/r300_screen_buffer.h
+++ b/src/gallium/drivers/r300/r300_screen_buffer.h
@@ -116,25 +116,4 @@ static INLINE boolean r300_add_texture(struct r300_winsys_screen *rws,
return rws->add_buffer(rws, tex->buffer, rd, wr);
}
-static INLINE void r300_buffer_write_reloc(struct r300_winsys_screen *rws,
- struct r300_buffer *buf,
- enum r300_buffer_domain rd,
- enum r300_buffer_domain wd,
- uint32_t flags)
-{
- if (!buf->buf)
- return;
-
- rws->write_cs_reloc(rws, buf->buf, rd, wd, flags);
-}
-
-static INLINE void r300_texture_write_reloc(struct r300_winsys_screen *rws,
- struct r300_texture *texture,
- enum r300_buffer_domain rd,
- enum r300_buffer_domain wd,
- uint32_t flags)
-{
- rws->write_cs_reloc(rws, texture->buffer, rd, wd, flags);
-}
-
#endif
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index cfec8ac2b7..15de533778 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -31,12 +31,12 @@
#include "pipe/p_config.h"
+#include "r300_cb.h"
#include "r300_context.h"
#include "r300_emit.h"
#include "r300_reg.h"
#include "r300_screen.h"
#include "r300_screen_buffer.h"
-#include "r300_state.h"
#include "r300_state_inlines.h"
#include "r300_fs.h"
#include "r300_texture.h"
@@ -183,6 +183,12 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
{
struct r300_screen* r300screen = r300_screen(pipe->screen);
struct r300_blend_state* blend = CALLOC_STRUCT(r300_blend_state);
+ uint32_t blend_control = 0; /* R300_RB3D_CBLEND: 0x4e04 */
+ uint32_t alpha_blend_control = 0; /* R300_RB3D_ABLEND: 0x4e08 */
+ uint32_t color_channel_mask = 0; /* R300_RB3D_COLOR_CHANNEL_MASK: 0x4e0c */
+ uint32_t rop = 0; /* R300_RB3D_ROPCNTL: 0x4e18 */
+ uint32_t dither = 0; /* R300_RB3D_DITHER_CTL: 0x4e50 */
+ CB_LOCALS;
if (state->rt[0].blend_enable)
{
@@ -196,7 +202,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
/* despite the name, ALPHA_BLEND_ENABLE has nothing to do with alpha,
* this is just the crappy D3D naming */
- blend->blend_control = R300_ALPHA_BLEND_ENABLE |
+ blend_control = R300_ALPHA_BLEND_ENABLE |
r300_translate_blend_function(eqRGB) |
( r300_translate_blend_factor(srcRGB) << R300_SRC_BLEND_SHIFT) |
( r300_translate_blend_factor(dstRGB) << R300_DST_BLEND_SHIFT);
@@ -220,7 +226,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
srcA == PIPE_BLENDFACTOR_INV_DST_ALPHA ||
srcRGB == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE) {
/* Enable reading from the colorbuffer. */
- blend->blend_control |= R300_READ_ENABLE;
+ blend_control |= R300_READ_ENABLE;
if (r300screen->caps.is_r500) {
/* Optimization: Depending on incoming pixels, we can
@@ -233,7 +239,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
(dstA == PIPE_BLENDFACTOR_SRC_COLOR ||
dstA == PIPE_BLENDFACTOR_SRC_ALPHA ||
dstA == PIPE_BLENDFACTOR_ZERO)) {
- blend->blend_control |= R500_SRC_ALPHA_0_NO_READ;
+ blend_control |= R500_SRC_ALPHA_0_NO_READ;
}
/* Disable reading if SRC_ALPHA == 1. */
@@ -242,7 +248,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
(dstA == PIPE_BLENDFACTOR_INV_SRC_COLOR ||
dstA == PIPE_BLENDFACTOR_INV_SRC_ALPHA ||
dstA == PIPE_BLENDFACTOR_ZERO)) {
- blend->blend_control |= R500_SRC_ALPHA_1_NO_READ;
+ blend_control |= R500_SRC_ALPHA_1_NO_READ;
}
}
}
@@ -272,31 +278,31 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
* pixels.
*/
if (blend_discard_if_src_alpha_0(srcRGB, srcA, dstRGB, dstA)) {
- blend->blend_control |= R300_DISCARD_SRC_PIXELS_SRC_ALPHA_0;
+ blend_control |= R300_DISCARD_SRC_PIXELS_SRC_ALPHA_0;
} else if (blend_discard_if_src_alpha_1(srcRGB, srcA,
dstRGB, dstA)) {
- blend->blend_control |= R300_DISCARD_SRC_PIXELS_SRC_ALPHA_1;
+ blend_control |= R300_DISCARD_SRC_PIXELS_SRC_ALPHA_1;
} else if (blend_discard_if_src_color_0(srcRGB, srcA,
dstRGB, dstA)) {
- blend->blend_control |= R300_DISCARD_SRC_PIXELS_SRC_COLOR_0;
+ blend_control |= R300_DISCARD_SRC_PIXELS_SRC_COLOR_0;
} else if (blend_discard_if_src_color_1(srcRGB, srcA,
dstRGB, dstA)) {
- blend->blend_control |= R300_DISCARD_SRC_PIXELS_SRC_COLOR_1;
+ blend_control |= R300_DISCARD_SRC_PIXELS_SRC_COLOR_1;
} else if (blend_discard_if_src_alpha_color_0(srcRGB, srcA,
dstRGB, dstA)) {
- blend->blend_control |=
+ blend_control |=
R300_DISCARD_SRC_PIXELS_SRC_ALPHA_COLOR_0;
} else if (blend_discard_if_src_alpha_color_1(srcRGB, srcA,
dstRGB, dstA)) {
- blend->blend_control |=
+ blend_control |=
R300_DISCARD_SRC_PIXELS_SRC_ALPHA_COLOR_1;
}
}
/* separate alpha */
if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB) {
- blend->blend_control |= R300_SEPARATE_ALPHA_ENABLE;
- blend->alpha_blend_control =
+ blend_control |= R300_SEPARATE_ALPHA_ENABLE;
+ alpha_blend_control =
r300_translate_blend_function(eqA) |
(r300_translate_blend_factor(srcA) << R300_SRC_BLEND_SHIFT) |
(r300_translate_blend_factor(dstA) << R300_DST_BLEND_SHIFT);
@@ -305,21 +311,21 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
/* PIPE_LOGICOP_* don't need to be translated, fortunately. */
if (state->logicop_enable) {
- blend->rop = R300_RB3D_ROPCNTL_ROP_ENABLE |
+ rop = R300_RB3D_ROPCNTL_ROP_ENABLE |
(state->logicop_func) << R300_RB3D_ROPCNTL_ROP_SHIFT;
}
/* Color channel masks for all MRTs. */
- blend->color_channel_mask = bgra_cmask(state->rt[0].colormask);
+ color_channel_mask = bgra_cmask(state->rt[0].colormask);
if (r300screen->caps.is_r500 && state->independent_blend_enable) {
if (state->rt[1].blend_enable) {
- blend->color_channel_mask |= bgra_cmask(state->rt[1].colormask) << 4;
+ color_channel_mask |= bgra_cmask(state->rt[1].colormask) << 4;
}
if (state->rt[2].blend_enable) {
- blend->color_channel_mask |= bgra_cmask(state->rt[2].colormask) << 8;
+ color_channel_mask |= bgra_cmask(state->rt[2].colormask) << 8;
}
if (state->rt[3].blend_enable) {
- blend->color_channel_mask |= bgra_cmask(state->rt[3].colormask) << 12;
+ color_channel_mask |= bgra_cmask(state->rt[3].colormask) << 12;
}
}
@@ -330,11 +336,31 @@ static void* r300_create_blend_state(struct pipe_context* pipe,
* This could be revisited if we ever get quality or conformance hints.
*
if (state->dither) {
- blend->dither = R300_RB3D_DITHER_CTL_DITHER_MODE_LUT |
+ dither = R300_RB3D_DITHER_CTL_DITHER_MODE_LUT |
R300_RB3D_DITHER_CTL_ALPHA_DITHER_MODE_LUT;
}
*/
+ /* Build a command buffer. */
+ BEGIN_CB(blend->cb, 8);
+ OUT_CB_REG(R300_RB3D_ROPCNTL, rop);
+ OUT_CB_REG_SEQ(R300_RB3D_CBLEND, 3);
+ OUT_CB(blend_control);
+ OUT_CB(alpha_blend_control);
+ OUT_CB(color_channel_mask);
+ OUT_CB_REG(R300_RB3D_DITHER_CTL, dither);
+ END_CB;
+
+ /* The same as above, but with no colorbuffer reads and writes. */
+ BEGIN_CB(blend->cb_no_readwrite, 8);
+ OUT_CB_REG(R300_RB3D_ROPCNTL, rop);
+ OUT_CB_REG_SEQ(R300_RB3D_CBLEND, 3);
+ OUT_CB(0);
+ OUT_CB(0);
+ OUT_CB(0);
+ OUT_CB_REG(R300_RB3D_DITHER_CTL, dither);
+ END_CB;
+
return (void*)blend;
}
@@ -368,20 +394,26 @@ static void r300_set_blend_color(struct pipe_context* pipe,
struct r300_context* r300 = r300_context(pipe);
struct r300_blend_color_state* state =
(struct r300_blend_color_state*)r300->blend_color_state.state;
- union util_color uc;
+ CB_LOCALS;
- util_pack_color(color->color, PIPE_FORMAT_B8G8R8A8_UNORM, &uc);
- state->blend_color = uc.ui;
+ if (r300->screen->caps.is_r500) {
+ /* XXX if FP16 blending is enabled, we should use the FP16 format */
+ BEGIN_CB(state->cb, 3);
+ OUT_CB_REG_SEQ(R500_RB3D_CONSTANT_COLOR_AR, 2);
+ OUT_CB(float_to_fixed10(color->color[0]) |
+ (float_to_fixed10(color->color[3]) << 16));
+ OUT_CB(float_to_fixed10(color->color[2]) |
+ (float_to_fixed10(color->color[1]) << 16));
+ END_CB;
+ } else {
+ union util_color uc;
+ util_pack_color(color->color, PIPE_FORMAT_B8G8R8A8_UNORM, &uc);
- /* XXX if FP16 blending is enabled, we should use the FP16 format */
- state->blend_color_red_alpha =
- float_to_fixed10(color->color[0]) |
- (float_to_fixed10(color->color[3]) << 16);
- state->blend_color_green_blue =
- float_to_fixed10(color->color[2]) |
- (float_to_fixed10(color->color[1]) << 16);
+ BEGIN_CB(state->cb, 2);
+ OUT_CB_REG(R300_RB3D_BLEND_COLOR, uc.ui);
+ END_CB;
+ }
- r300->blend_color_state.size = r300->screen->caps.is_r500 ? 3 : 2;
r300->blend_color_state.dirty = TRUE;
}
@@ -389,18 +421,27 @@ static void r300_set_clip_state(struct pipe_context* pipe,
const struct pipe_clip_state* state)
{
struct r300_context* r300 = r300_context(pipe);
+ struct r300_clip_state *clip =
+ (struct r300_clip_state*)r300->clip_state.state;
+ CB_LOCALS;
- r300->clip = *state;
+ clip->clip = *state;
if (r300->screen->caps.has_tcl) {
- memcpy(r300->clip_state.state, state, sizeof(struct pipe_clip_state));
- r300->clip_state.size = 29;
+ BEGIN_CB(clip->cb, 29);
+ OUT_CB_REG(R300_VAP_PVS_VECTOR_INDX_REG,
+ (r300->screen->caps.is_r500 ?
+ R500_PVS_UCP_START : R300_PVS_UCP_START));
+ OUT_CB_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, 6 * 4);
+ OUT_CB_TABLE(state->ucp, 6 * 4);
+ OUT_CB_REG(R300_VAP_CLIP_CNTL, ((1 << state->nr) - 1) |
+ R300_PS_UCP_MODE_CLIP_AS_TRIFAN);
+ END_CB;
r300->clip_state.dirty = TRUE;
} else {
draw_flush(r300->draw);
draw_set_clip_state(r300->draw, state);
- r300->clip_state.size = 2;
}
}
@@ -422,6 +463,9 @@ static void*
{
struct r300_capabilities *caps = &r300_screen(pipe->screen)->caps;
struct r300_dsa_state* dsa = CALLOC_STRUCT(r300_dsa_state);
+ CB_LOCALS;
+
+ dsa->dsa = *state;
/* Depth test setup. */
if (state->depth.enabled) {
@@ -494,9 +538,43 @@ static void*
dsa->alpha_function |= R500_FG_ALPHA_FUNC_8BIT;
}
+ BEGIN_CB(&dsa->cb_begin, 8);
+ OUT_CB_REG(R300_FG_ALPHA_FUNC, dsa->alpha_function);
+ OUT_CB_REG_SEQ(R300_ZB_CNTL, 3);
+ OUT_CB(dsa->z_buffer_control);
+ OUT_CB(dsa->z_stencil_control);
+ OUT_CB(dsa->stencil_ref_mask);
+ OUT_CB_REG(R500_ZB_STENCILREFMASK_BF, dsa->stencil_ref_bf);
+ END_CB;
+
+ BEGIN_CB(dsa->cb_no_readwrite, 8);
+ OUT_CB_REG(R300_FG_ALPHA_FUNC, dsa->alpha_function);
+ OUT_CB_REG_SEQ(R300_ZB_CNTL, 3);
+ OUT_CB(0);
+ OUT_CB(0);
+ OUT_CB(0);
+ OUT_CB_REG(R500_ZB_STENCILREFMASK_BF, 0);
+ END_CB;
+
return (void*)dsa;
}
+static void r300_dsa_inject_stencilref(struct r300_context *r300)
+{
+ struct r300_dsa_state *dsa =
+ (struct r300_dsa_state*)r300->dsa_state.state;
+
+ if (!dsa)
+ return;
+
+ dsa->stencil_ref_mask =
+ (dsa->stencil_ref_mask & ~R300_STENCILREF_MASK) |
+ r300->stencil_ref.ref_value[0];
+ dsa->stencil_ref_bf =
+ (dsa->stencil_ref_bf & ~R300_STENCILREF_MASK) |
+ r300->stencil_ref.ref_value[1];
+}
+
/* Bind DSA state. */
static void r300_bind_dsa_state(struct pipe_context* pipe,
void* state)
@@ -508,6 +586,8 @@ static void r300_bind_dsa_state(struct pipe_context* pipe,
}
UPDATE_STATE(state, r300->dsa_state);
+
+ r300_dsa_inject_stencilref(r300);
}
/* Free DSA state. */
@@ -523,6 +603,8 @@ static void r300_set_stencil_ref(struct pipe_context* pipe,
struct r300_context* r300 = r300_context(pipe);
r300->stencil_ref = *sr;
+
+ r300_dsa_inject_stencilref(r300);
r300->dsa_state.dirty = TRUE;
}
@@ -577,21 +659,34 @@ static void r300_print_fb_surf_info(struct pipe_surface *surf, unsigned index,
tex->last_level, util_format_short_name(tex->format));
}
+static void copy_framebuffer_state(struct pipe_framebuffer_state *dst,
+ const struct pipe_framebuffer_state *src)
+{
+ unsigned i;
+
+ for (i = 0; i < src->nr_cbufs; i++) {
+ pipe_surface_reference(&dst->cbufs[i], src->cbufs[i]);
+ }
+ for (; i < dst->nr_cbufs; i++) {
+ pipe_surface_reference(&dst->cbufs[i], NULL);
+ }
+ pipe_surface_reference(&dst->zsbuf, src->zsbuf);
+
+ dst->nr_cbufs = src->nr_cbufs;
+ dst->width = src->width;
+ dst->height = src->height;
+}
+
static void
r300_set_framebuffer_state(struct pipe_context* pipe,
const struct pipe_framebuffer_state* state)
{
struct r300_context* r300 = r300_context(pipe);
+ struct r300_aa_state *aa = (struct r300_aa_state*)r300->aa_state.state;
struct pipe_framebuffer_state *old_state = r300->fb_state.state;
unsigned max_width, max_height, i;
uint32_t zbuffer_bpp = 0;
- if (state->nr_cbufs > 4) {
- fprintf(stderr, "r300: Implementation error: Too many MRTs in %s, "
- "refusing to bind framebuffer state!\n", __FUNCTION__);
- return;
- }
-
if (r300->screen->caps.is_r500) {
max_width = max_height = 4096;
} else if (r300->screen->caps.is_r400) {
@@ -610,7 +705,11 @@ static void
draw_flush(r300->draw);
}
+ r300->gpu_flush.dirty = TRUE;
+ r300->aa_state.dirty = TRUE;
r300->fb_state.dirty = TRUE;
+ r300->hyperz_state.dirty = TRUE;
+ r300->fb_state_pipelined.dirty = TRUE;
/* If nr_cbufs is changed from zero to non-zero or vice versa... */
if (!!old_state->nr_cbufs != !!state->nr_cbufs) {
@@ -624,10 +723,12 @@ static void
/* The tiling flags are dependent on the surface miplevel, unfortunately. */
r300_fb_set_tiling_flags(r300, r300->fb_state.state, state);
- memcpy(r300->fb_state.state, state, sizeof(struct pipe_framebuffer_state));
+ copy_framebuffer_state(r300->fb_state.state, state);
- r300->fb_state.size = (10 * state->nr_cbufs) + (2 * (4 - state->nr_cbufs)) +
- (state->zsbuf ? 10 : 0) + 9;
+ r300->fb_state.size =
+ 2 +
+ (8 * state->nr_cbufs) +
+ (state->zsbuf ? (r300->screen->caps.has_hiz ? 18 : 14) : 0);
/* Polygon offset depends on the zbuffer bit depth. */
if (state->zsbuf && r300->polygon_offset_enabled) {
@@ -646,6 +747,30 @@ static void
}
}
+ /* Set up AA config. */
+ if (r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0)) {
+ if (state->nr_cbufs && state->cbufs[0]->texture->nr_samples > 1) {
+ aa->aa_config = R300_GB_AA_CONFIG_AA_ENABLE;
+
+ switch (state->cbufs[0]->texture->nr_samples) {
+ case 2:
+ aa->aa_config |= R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_2;
+ break;
+ case 3:
+ aa->aa_config |= R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_3;
+ break;
+ case 4:
+ aa->aa_config |= R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_4;
+ break;
+ case 6:
+ aa->aa_config |= R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_6;
+ break;
+ }
+ } else {
+ aa->aa_config = 0;
+ }
+ }
+
if (DBG_ON(r300, DBG_FB)) {
fprintf(stderr, "r300: set_framebuffer_state:\n");
for (i = 0; i < state->nr_cbufs; i++) {
@@ -679,13 +804,12 @@ void r300_mark_fs_code_dirty(struct r300_context *r300)
r300->fs.dirty = TRUE;
r300->fs_rc_constant_state.dirty = TRUE;
r300->fs_constants.dirty = TRUE;
+ r300->fs.size = fs->shader->cb_code_size;
if (r300->screen->caps.is_r500) {
- r300->fs.size = r500_get_fs_atom_size(r300);
r300->fs_rc_constant_state.size = fs->shader->rc_state_count * 7;
r300->fs_constants.size = fs->shader->externals_count * 4 + 3;
} else {
- r300->fs.size = r300_get_fs_atom_size(r300);
r300->fs_rc_constant_state.size = fs->shader->rc_state_count * 5;
r300->fs_constants.size = fs->shader->externals_count * 4 + 1;
}
@@ -719,6 +843,7 @@ static void r300_delete_fs_state(struct pipe_context* pipe, void* shader)
tmp = ptr;
ptr = ptr->next;
rc_constants_destroy(&tmp->code.constants);
+ FREE(tmp->cb_code);
FREE(tmp);
}
FREE((void*)fs->state.tokens);
@@ -744,6 +869,27 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
struct r300_rs_state* rs = CALLOC_STRUCT(r300_rs_state);
int i;
float psiz;
+ uint32_t vap_control_status; /* R300_VAP_CNTL_STATUS: 0x2140 */
+ uint32_t point_size; /* R300_GA_POINT_SIZE: 0x421c */
+ uint32_t point_minmax; /* R300_GA_POINT_MINMAX: 0x4230 */
+ uint32_t line_control; /* R300_GA_LINE_CNTL: 0x4234 */
+ uint32_t polygon_offset_enable; /* R300_SU_POLY_OFFSET_ENABLE: 0x42b4 */
+ uint32_t cull_mode; /* R300_SU_CULL_MODE: 0x42b8 */
+ uint32_t line_stipple_config; /* R300_GA_LINE_STIPPLE_CONFIG: 0x4328 */
+ uint32_t line_stipple_value; /* R300_GA_LINE_STIPPLE_VALUE: 0x4260 */
+ uint32_t polygon_mode; /* R300_GA_POLY_MODE: 0x4288 */
+ uint32_t clip_rule; /* R300_SC_CLIP_RULE: 0x43D0 */
+
+ /* Specifies top of Raster pipe specific enable controls,
+ * i.e. texture coordinates stuffing for points, lines, triangles */
+ uint32_t stuffing_enable; /* R300_GB_ENABLE: 0x4008 */
+
+ /* Point sprites texture coordinates, 0: lower left, 1: upper right */
+ float point_texcoord_left; /* R300_GA_POINT_S0: 0x4200 */
+ float point_texcoord_bottom; /* R300_GA_POINT_T0: 0x4204 */
+ float point_texcoord_right; /* R300_GA_POINT_S1: 0x4208 */
+ float point_texcoord_top; /* R300_GA_POINT_T1: 0x420c */
+ CB_LOCALS;
/* Copy rasterizer state. */
rs->rs = *state;
@@ -753,18 +899,18 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
rs->rs_draw.sprite_coord_enable = 0; /* We can do this in HW. */
#ifdef PIPE_ARCH_LITTLE_ENDIAN
- rs->vap_control_status = R300_VC_NO_SWAP;
+ vap_control_status = R300_VC_NO_SWAP;
#else
- rs->vap_control_status = R300_VC_32BIT_SWAP;
+ vap_control_status = R300_VC_32BIT_SWAP;
#endif
/* If no TCL engine is present, turn off the HW TCL. */
if (!r300_screen(pipe->screen)->caps.has_tcl) {
- rs->vap_control_status |= R300_VAP_TCL_BYPASS;
+ vap_control_status |= R300_VAP_TCL_BYPASS;
}
/* Point size width and height. */
- rs->point_size =
+ point_size =
pack_float_16_6x(state->point_size) |
(pack_float_16_6x(state->point_size) << R300_POINTSIZE_X_SHIFT);
@@ -774,68 +920,67 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
* Clamp to [0, max FB size] */
psiz = pipe->screen->get_paramf(pipe->screen,
PIPE_CAP_MAX_POINT_WIDTH);
- rs->point_minmax =
+ point_minmax =
pack_float_16_6x(psiz) << R300_GA_POINT_MINMAX_MAX_SHIFT;
} else {
/* We cannot disable the point-size vertex output,
* so clamp it. */
psiz = state->point_size;
- rs->point_minmax =
+ point_minmax =
(pack_float_16_6x(psiz) << R300_GA_POINT_MINMAX_MIN_SHIFT) |
(pack_float_16_6x(psiz) << R300_GA_POINT_MINMAX_MAX_SHIFT);
}
/* Line control. */
- rs->line_control = pack_float_16_6x(state->line_width) |
+ line_control = pack_float_16_6x(state->line_width) |
R300_GA_LINE_CNTL_END_TYPE_COMP;
/* Enable polygon mode */
+ polygon_mode = 0;
if (state->fill_front != PIPE_POLYGON_MODE_FILL ||
state->fill_back != PIPE_POLYGON_MODE_FILL) {
- rs->polygon_mode = R300_GA_POLY_MODE_DUAL;
+ polygon_mode = R300_GA_POLY_MODE_DUAL;
}
/* Front face */
if (state->front_ccw)
- rs->cull_mode = R300_FRONT_FACE_CCW;
+ cull_mode = R300_FRONT_FACE_CCW;
else
- rs->cull_mode = R300_FRONT_FACE_CW;
+ cull_mode = R300_FRONT_FACE_CW;
/* Polygon offset */
+ polygon_offset_enable = 0;
if (util_get_offset(state, state->fill_front)) {
- rs->polygon_offset_enable |= R300_FRONT_ENABLE;
+ polygon_offset_enable |= R300_FRONT_ENABLE;
}
if (util_get_offset(state, state->fill_back)) {
- rs->polygon_offset_enable |= R300_BACK_ENABLE;
+ polygon_offset_enable |= R300_BACK_ENABLE;
}
+ rs->polygon_offset_enable = polygon_offset_enable != 0;
+
/* Polygon mode */
- if (rs->polygon_mode) {
- rs->polygon_mode |=
+ if (polygon_mode) {
+ polygon_mode |=
r300_translate_polygon_mode_front(state->fill_front);
- rs->polygon_mode |=
+ polygon_mode |=
r300_translate_polygon_mode_back(state->fill_back);
}
if (state->cull_face & PIPE_FACE_FRONT) {
- rs->cull_mode |= R300_CULL_FRONT;
+ cull_mode |= R300_CULL_FRONT;
}
if (state->cull_face & PIPE_FACE_BACK) {
- rs->cull_mode |= R300_CULL_BACK;
- }
-
- if (rs->polygon_offset_enable) {
- rs->depth_offset = state->offset_units;
- rs->depth_scale = state->offset_scale;
+ cull_mode |= R300_CULL_BACK;
}
if (state->line_stipple_enable) {
- rs->line_stipple_config =
+ line_stipple_config =
R300_GA_LINE_STIPPLE_CONFIG_LINE_RESET_LINE |
(fui((float)state->line_stipple_factor) &
R300_GA_LINE_STIPPLE_CONFIG_STIPPLE_SCALE_MASK);
/* XXX this might need to be scaled up */
- rs->line_stipple_value = state->line_stipple_pattern;
+ line_stipple_value = state->line_stipple_pattern;
}
if (state->flatshade) {
@@ -844,32 +989,80 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
rs->color_control = R300_SHADE_MODEL_SMOOTH;
}
- rs->clip_rule = state->scissor ? 0xAAAA : 0xFFFF;
+ clip_rule = state->scissor ? 0xAAAA : 0xFFFF;
/* Point sprites */
+ stuffing_enable = 0;
if (state->sprite_coord_enable) {
- rs->stuffing_enable = R300_GB_POINT_STUFF_ENABLE;
+ stuffing_enable = R300_GB_POINT_STUFF_ENABLE;
for (i = 0; i < 8; i++) {
if (state->sprite_coord_enable & (1 << i))
- rs->stuffing_enable |=
+ stuffing_enable |=
R300_GB_TEX_STR << (R300_GB_TEX0_SOURCE_SHIFT + (i*2));
}
- rs->point_texcoord_left = 0.0f;
- rs->point_texcoord_right = 1.0f;
+ point_texcoord_left = 0.0f;
+ point_texcoord_right = 1.0f;
switch (state->sprite_coord_mode) {
case PIPE_SPRITE_COORD_UPPER_LEFT:
- rs->point_texcoord_top = 0.0f;
- rs->point_texcoord_bottom = 1.0f;
+ point_texcoord_top = 0.0f;
+ point_texcoord_bottom = 1.0f;
break;
case PIPE_SPRITE_COORD_LOWER_LEFT:
- rs->point_texcoord_top = 1.0f;
- rs->point_texcoord_bottom = 0.0f;
+ point_texcoord_top = 1.0f;
+ point_texcoord_bottom = 0.0f;
break;
}
}
+ /* Build the main command buffer. */
+ BEGIN_CB(rs->cb_main, 25);
+ OUT_CB_REG(R300_VAP_CNTL_STATUS, vap_control_status);
+ OUT_CB_REG(R300_GA_POINT_SIZE, point_size);
+ OUT_CB_REG_SEQ(R300_GA_POINT_MINMAX, 2);
+ OUT_CB(point_minmax);
+ OUT_CB(line_control);
+ OUT_CB_REG_SEQ(R300_SU_POLY_OFFSET_ENABLE, 2);
+ OUT_CB(polygon_offset_enable);
+ rs->cull_mode_index = 9;
+ OUT_CB(cull_mode);
+ OUT_CB_REG(R300_GA_LINE_STIPPLE_CONFIG, line_stipple_config);
+ OUT_CB_REG(R300_GA_LINE_STIPPLE_VALUE, line_stipple_value);
+ OUT_CB_REG(R300_GA_POLY_MODE, polygon_mode);
+ OUT_CB_REG(R300_SC_CLIP_RULE, clip_rule);
+ OUT_CB_REG(R300_GB_ENABLE, stuffing_enable);
+ OUT_CB_REG_SEQ(R300_GA_POINT_S0, 4);
+ OUT_CB_32F(point_texcoord_left);
+ OUT_CB_32F(point_texcoord_bottom);
+ OUT_CB_32F(point_texcoord_right);
+ OUT_CB_32F(point_texcoord_top);
+ END_CB;
+
+ /* Build the two command buffers for polygon offset setup. */
+ if (polygon_offset_enable) {
+ float scale = state->offset_scale * 12;
+ float offset = state->offset_units * 4;
+
+ BEGIN_CB(rs->cb_poly_offset_zb16, 5);
+ OUT_CB_REG_SEQ(R300_SU_POLY_OFFSET_FRONT_SCALE, 4);
+ OUT_CB_32F(scale);
+ OUT_CB_32F(offset);
+ OUT_CB_32F(scale);
+ OUT_CB_32F(offset);
+ END_CB;
+
+ offset = state->offset_units * 2;
+
+ BEGIN_CB(rs->cb_poly_offset_zb24, 5);
+ OUT_CB_REG_SEQ(R300_SU_POLY_OFFSET_FRONT_SCALE, 4);
+ OUT_CB_32F(scale);
+ OUT_CB_32F(offset);
+ OUT_CB_32F(scale);
+ OUT_CB_32F(offset);
+ END_CB;
+ }
+
return (void*)rs;
}
@@ -899,7 +1092,7 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
}
UPDATE_STATE(state, r300->rs_state);
- r300->rs_state.size = 27 + (r300->polygon_offset_enabled ? 5 : 0);
+ r300->rs_state.size = 25 + (r300->polygon_offset_enabled ? 5 : 0);
if (last_sprite_coord_enable != r300->sprite_coord_enable ||
last_two_sided_color != r300->two_sided_color) {
@@ -925,10 +1118,34 @@ static void*
sampler->state = *state;
+ /* r300 doesn't handle CLAMP and MIRROR_CLAMP correctly when either MAG
+ * or MIN filter is NEAREST. Since texwrap produces same results
+ * for CLAMP and CLAMP_TO_EDGE, we use them instead. */
+ if (sampler->state.min_img_filter == PIPE_TEX_FILTER_NEAREST ||
+ sampler->state.mag_img_filter == PIPE_TEX_FILTER_NEAREST) {
+ /* Wrap S. */
+ if (sampler->state.wrap_s == PIPE_TEX_WRAP_CLAMP)
+ sampler->state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ else if (sampler->state.wrap_s == PIPE_TEX_WRAP_MIRROR_CLAMP)
+ sampler->state.wrap_s = PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE;
+
+ /* Wrap T. */
+ if (sampler->state.wrap_t == PIPE_TEX_WRAP_CLAMP)
+ sampler->state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ else if (sampler->state.wrap_t == PIPE_TEX_WRAP_MIRROR_CLAMP)
+ sampler->state.wrap_t = PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE;
+
+ /* Wrap R. */
+ if (sampler->state.wrap_r == PIPE_TEX_WRAP_CLAMP)
+ sampler->state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ else if (sampler->state.wrap_r == PIPE_TEX_WRAP_MIRROR_CLAMP)
+ sampler->state.wrap_r = PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE;
+ }
+
sampler->filter0 |=
- (r300_translate_wrap(state->wrap_s) << R300_TX_WRAP_S_SHIFT) |
- (r300_translate_wrap(state->wrap_t) << R300_TX_WRAP_T_SHIFT) |
- (r300_translate_wrap(state->wrap_r) << R300_TX_WRAP_R_SHIFT);
+ (r300_translate_wrap(sampler->state.wrap_s) << R300_TX_WRAP_S_SHIFT) |
+ (r300_translate_wrap(sampler->state.wrap_t) << R300_TX_WRAP_T_SHIFT) |
+ (r300_translate_wrap(sampler->state.wrap_r) << R300_TX_WRAP_R_SHIFT);
sampler->filter0 |= r300_translate_tex_filters(state->min_img_filter,
state->mag_img_filter,
@@ -995,6 +1212,31 @@ static void r300_delete_sampler_state(struct pipe_context* pipe, void* state)
FREE(state);
}
+static uint32_t r300_assign_texture_cache_region(unsigned index, unsigned num)
+{
+ /* This looks like a hack, but I believe it's suppose to work like
+ * that. To illustrate how this works, let's assume you have 5 textures.
+ * From docs, 5 and the successive numbers are:
+ *
+ * FOURTH_1 = 5
+ * FOURTH_2 = 6
+ * FOURTH_3 = 7
+ * EIGHTH_0 = 8
+ * EIGHTH_1 = 9
+ *
+ * First 3 textures will get 3/4 of size of the cache, divived evenly
+ * between them. The last 1/4 of the cache must be divided between
+ * the last 2 textures, each will therefore get 1/8 of the cache.
+ * Why not just to use "5 + texture_index" ?
+ *
+ * This simple trick works for all "num" <= 16.
+ */
+ if (num <= 1)
+ return R300_TX_CACHE(R300_TX_CACHE_WHOLE);
+ else
+ return R300_TX_CACHE(num + index);
+}
+
static void r300_set_fragment_sampler_views(struct pipe_context* pipe,
unsigned count,
struct pipe_sampler_view** views)
@@ -1003,7 +1245,7 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe,
struct r300_textures_state* state =
(struct r300_textures_state*)r300->textures_state.state;
struct r300_texture *texture;
- unsigned i;
+ unsigned i, real_num_views = 0, view_index = 0;
unsigned tex_units = r300->screen->caps.num_tex_units;
boolean dirty_tex = FALSE;
@@ -1011,6 +1253,12 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe,
return;
}
+ /* Calculate the real number of views. */
+ for (i = 0; i < count; i++) {
+ if (views[i])
+ real_num_views++;
+ }
+
for (i = 0; i < count; i++) {
if (&state->sampler_views[i]->base != views[i]) {
pipe_sampler_view_reference(
@@ -1030,6 +1278,10 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe,
if (texture->uses_pitch) {
r300->fs_rc_constant_state.dirty = TRUE;
}
+
+ state->sampler_views[i]->texcache_region =
+ r300_assign_texture_cache_region(view_index, real_num_views);
+ view_index++;
}
}
@@ -1167,15 +1419,15 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe,
if (r300->screen->caps.has_tcl) {
/* HW TCL. */
- /* Check if the stride is aligned to the size of DWORD. */
+ r300->incompatible_vb_layout = FALSE;
+
+ /* Check if the strides and offsets are aligned to the size of DWORD. */
for (i = 0; i < count; i++) {
if (buffers[i].buffer) {
- if (buffers[i].stride % 4 != 0) {
- // XXX Shouldn't we align the buffer?
- fprintf(stderr, "r300: set_vertex_buffers: "
- "Unaligned buffer stride %i isn't supported.\n",
- buffers[i].stride);
- abort();
+ if (buffers[i].stride % 4 != 0 ||
+ buffers[i].buffer_offset % 4 != 0) {
+ r300->incompatible_vb_layout = TRUE;
+ break;
}
}
}
@@ -1248,7 +1500,7 @@ static void r300_vertex_psc(struct r300_vertex_element_state *velems)
* so PSC should just route stuff based on the vertex elements,
* and not on attrib information. */
for (i = 0; i < velems->count; i++) {
- format = velems->velem[i].src_format;
+ format = velems->hw_format[i];
type = r300_translate_vertex_data_type(format);
if (type == R300_INVALID_FORMAT) {
@@ -1280,12 +1532,15 @@ static void r300_vertex_psc(struct r300_vertex_element_state *velems)
vstream->count = (i >> 1) + 1;
}
+#define FORMAT_REPLACE(what, withwhat) \
+ case PIPE_FORMAT_##what: *format = PIPE_FORMAT_##withwhat; break
+
static void* r300_create_vertex_elements_state(struct pipe_context* pipe,
unsigned count,
const struct pipe_vertex_element* attribs)
{
struct r300_vertex_element_state *velems;
- unsigned i, size;
+ unsigned i;
enum pipe_format *format;
assert(count <= PIPE_MAX_ATTRIBS);
@@ -1295,86 +1550,68 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe,
memcpy(velems->velem, attribs, sizeof(struct pipe_vertex_element) * count);
if (r300_screen(pipe->screen)->caps.has_tcl) {
- r300_vertex_psc(velems);
-
- /* Check if the format is aligned to the size of DWORD.
- * We only care about the blocksizes of the formats since
- * swizzles are already set up. */
+ /* Set the best hw format in case the original format is not
+ * supported by hw. */
for (i = 0; i < count; i++) {
- format = &velems->velem[i].src_format;
+ velems->hw_format[i] = velems->velem[i].src_format;
+ format = &velems->hw_format[i];
- /* Replace some formats with their aligned counterparts,
- * this is OK because we check for aligned strides too. */
+ /* This is basically the list of unsupported formats.
+ * For now we don't care about the alignment, that's going to
+ * be sorted out after the PSC setup. */
switch (*format) {
- /* Align to RGBA8. */
- case PIPE_FORMAT_R8_UNORM:
- case PIPE_FORMAT_R8G8_UNORM:
- case PIPE_FORMAT_R8G8B8_UNORM:
- *format = PIPE_FORMAT_R8G8B8A8_UNORM;
- continue;
- case PIPE_FORMAT_R8_SNORM:
- case PIPE_FORMAT_R8G8_SNORM:
- case PIPE_FORMAT_R8G8B8_SNORM:
- *format = PIPE_FORMAT_R8G8B8A8_SNORM;
- continue;
- case PIPE_FORMAT_R8_USCALED:
- case PIPE_FORMAT_R8G8_USCALED:
- case PIPE_FORMAT_R8G8B8_USCALED:
- *format = PIPE_FORMAT_R8G8B8A8_USCALED;
- continue;
- case PIPE_FORMAT_R8_SSCALED:
- case PIPE_FORMAT_R8G8_SSCALED:
- case PIPE_FORMAT_R8G8B8_SSCALED:
- *format = PIPE_FORMAT_R8G8B8A8_SSCALED;
- continue;
-
- /* Align to RG16. */
- case PIPE_FORMAT_R16_UNORM:
- *format = PIPE_FORMAT_R16G16_UNORM;
- continue;
- case PIPE_FORMAT_R16_SNORM:
- *format = PIPE_FORMAT_R16G16_SNORM;
- continue;
- case PIPE_FORMAT_R16_USCALED:
- *format = PIPE_FORMAT_R16G16_USCALED;
- continue;
- case PIPE_FORMAT_R16_SSCALED:
- *format = PIPE_FORMAT_R16G16_SSCALED;
- continue;
- case PIPE_FORMAT_R16_FLOAT:
- *format = PIPE_FORMAT_R16G16_FLOAT;
- continue;
-
- /* Align to RGBA16. */
- case PIPE_FORMAT_R16G16B16_UNORM:
- *format = PIPE_FORMAT_R16G16B16A16_UNORM;
- continue;
- case PIPE_FORMAT_R16G16B16_SNORM:
- *format = PIPE_FORMAT_R16G16B16A16_SNORM;
- continue;
- case PIPE_FORMAT_R16G16B16_USCALED:
- *format = PIPE_FORMAT_R16G16B16A16_USCALED;
- continue;
- case PIPE_FORMAT_R16G16B16_SSCALED:
- *format = PIPE_FORMAT_R16G16B16A16_SSCALED;
- continue;
- case PIPE_FORMAT_R16G16B16_FLOAT:
- *format = PIPE_FORMAT_R16G16B16A16_FLOAT;
- continue;
+ FORMAT_REPLACE(R64_FLOAT, R32_FLOAT);
+ FORMAT_REPLACE(R64G64_FLOAT, R32G32_FLOAT);
+ FORMAT_REPLACE(R64G64B64_FLOAT, R32G32B32_FLOAT);
+ FORMAT_REPLACE(R64G64B64A64_FLOAT, R32G32B32A32_FLOAT);
+
+ FORMAT_REPLACE(R32_UNORM, R32_FLOAT);
+ FORMAT_REPLACE(R32G32_UNORM, R32G32_FLOAT);
+ FORMAT_REPLACE(R32G32B32_UNORM, R32G32B32_FLOAT);
+ FORMAT_REPLACE(R32G32B32A32_UNORM, R32G32B32A32_FLOAT);
+
+ FORMAT_REPLACE(R32_USCALED, R32_FLOAT);
+ FORMAT_REPLACE(R32G32_USCALED, R32G32_FLOAT);
+ FORMAT_REPLACE(R32G32B32_USCALED, R32G32B32_FLOAT);
+ FORMAT_REPLACE(R32G32B32A32_USCALED,R32G32B32A32_FLOAT);
+
+ FORMAT_REPLACE(R32_SNORM, R32_FLOAT);
+ FORMAT_REPLACE(R32G32_SNORM, R32G32_FLOAT);
+ FORMAT_REPLACE(R32G32B32_SNORM, R32G32B32_FLOAT);
+ FORMAT_REPLACE(R32G32B32A32_SNORM, R32G32B32A32_FLOAT);
+
+ FORMAT_REPLACE(R32_SSCALED, R32_FLOAT);
+ FORMAT_REPLACE(R32G32_SSCALED, R32G32_FLOAT);
+ FORMAT_REPLACE(R32G32B32_SSCALED, R32G32B32_FLOAT);
+ FORMAT_REPLACE(R32G32B32A32_SSCALED,R32G32B32A32_FLOAT);
+
+ FORMAT_REPLACE(R32_FIXED, R32_FLOAT);
+ FORMAT_REPLACE(R32G32_FIXED, R32G32_FLOAT);
+ FORMAT_REPLACE(R32G32B32_FIXED, R32G32B32_FLOAT);
+ FORMAT_REPLACE(R32G32B32A32_FIXED, R32G32B32A32_FLOAT);
default:;
}
- size = util_format_get_blocksize(*format);
+ velems->incompatible_layout =
+ velems->incompatible_layout ||
+ velems->velem[i].src_format != velems->hw_format[i] ||
+ velems->velem[i].src_offset % 4 != 0;
+ }
- if (size % 4 != 0) {
- /* XXX Shouldn't we align the format? */
- fprintf(stderr, "r300_create_vertex_elements_state: "
- "Unaligned format %s:%i isn't supported\n",
- util_format_short_name(*format), size);
- assert(0);
- abort();
- }
+ /* Now setup PSC.
+ * The unused components will be replaced by (..., 0, 1). */
+ r300_vertex_psc(velems);
+
+ /* Align the formats to the size of DWORD.
+ * We only care about the blocksizes of the formats since
+ * swizzles are already set up.
+ * Also compute the vertex size. */
+ for (i = 0; i < count; i++) {
+ /* This is OK because we check for aligned strides too. */
+ velems->hw_format_size[i] =
+ align(util_format_get_blocksize(velems->hw_format[i]), 4);
+ velems->vertex_size_dwords += velems->hw_format_size[i] / 4;
}
}
}
@@ -1412,7 +1649,6 @@ static void* r300_create_vs_state(struct pipe_context* pipe,
const struct pipe_shader_state* shader)
{
struct r300_context* r300 = r300_context(pipe);
-
struct r300_vertex_shader* vs = CALLOC_STRUCT(r300_vertex_shader);
/* Copy state directly into shader. */
@@ -1490,7 +1726,7 @@ static void r300_set_constant_buffer(struct pipe_context *pipe,
struct r300_context* r300 = r300_context(pipe);
struct r300_constant_buffer *cbuf;
struct pipe_transfer *tr;
- void *mapped;
+ float *mapped;
int max_size = 0, max_size_bytes = 0, clamped_size = 0;
switch (shader) {
@@ -1529,10 +1765,20 @@ static void r300_set_constant_buffer(struct pipe_context *pipe,
fprintf(stderr, "r300: Max size of the constant buffer is "
"%i*4 floats.\n", max_size);
}
- clamped_size = MIN2(buf->width0, max_size_bytes);
- memcpy(cbuf->constants, mapped, clamped_size);
+ clamped_size = MIN2(buf->width0, max_size_bytes);
cbuf->count = clamped_size / (4 * sizeof(float));
+
+ if (shader == PIPE_SHADER_FRAGMENT && !r300->screen->caps.is_r500) {
+ unsigned i,j;
+
+ /* Convert constants to float24. */
+ for (i = 0; i < cbuf->count; i++)
+ for (j = 0; j < 4; j++)
+ cbuf->constants[i][j] = pack_float24(mapped[i*4+j]);
+ } else {
+ memcpy(cbuf->constants, mapped, clamped_size);
+ }
}
if (shader == PIPE_SHADER_VERTEX) {
diff --git a/src/gallium/drivers/r300/r300_state.h b/src/gallium/drivers/r300/r300_state.h
deleted file mode 100644
index 1d557506cf..0000000000
--- a/src/gallium/drivers/r300/r300_state.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2008 Marek Olšák <maraeo@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE. */
-
-#ifndef R300_STATE_H
-#define R300_STATE_H
-
-struct r300_context;
-
-void r300_mark_fs_code_dirty(struct r300_context *r300);
-
-#endif /* R300_STATE_H */
diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c
index cc75fad3bb..3aa8deb63c 100644
--- a/src/gallium/drivers/r300/r300_state_derived.c
+++ b/src/gallium/drivers/r300/r300_state_derived.c
@@ -31,7 +31,6 @@
#include "r300_hyperz.h"
#include "r300_screen.h"
#include "r300_shader_semantics.h"
-#include "r300_state.h"
#include "r300_state_derived.h"
#include "r300_state_inlines.h"
#include "r300_texture.h"
@@ -537,6 +536,10 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
UTIL_FORMAT_SWIZZLE_X
};
+ /* The KIL opcode fix, see below. */
+ if (!count && !r300->screen->caps.is_r500)
+ count = 1;
+
state->tx_enable = 0;
state->count = 0;
size = 2;
@@ -555,6 +558,9 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
texstate->filter1 = sampler->filter1;
texstate->border_color = sampler->border_color;
+ /* Assign a texture cache region. */
+ texstate->format.format1 |= view->texcache_region;
+
/* If compare mode is disabled, the sampler view swizzles
* are stored in the format.
* Otherwise, swizzles must be applied after the compare mode
@@ -613,6 +619,36 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
size += 16;
state->count = i+1;
+ } else {
+ /* For the KIL opcode to work on r3xx-r4xx, the texture unit
+ * assigned to this opcode (it's always the first one) must be
+ * enabled. Otherwise the opcode doesn't work.
+ *
+ * In order to not depend on the fragment shader, we just make
+ * the first unit enabled all the time. */
+ if (i == 0 && !r300->screen->caps.is_r500) {
+ pipe_sampler_view_reference(
+ (struct pipe_sampler_view**)&state->sampler_views[i],
+ &r300->texkill_sampler->base);
+
+ state->tx_enable |= 1 << i;
+
+ texstate = &state->regs[i];
+
+ /* Just set some valid state. */
+ texstate->format = r300->texkill_sampler->format;
+ texstate->filter0 =
+ r300_translate_tex_filters(PIPE_TEX_FILTER_NEAREST,
+ PIPE_TEX_FILTER_NEAREST,
+ PIPE_TEX_FILTER_NEAREST,
+ FALSE);
+ texstate->filter1 = 0;
+ texstate->border_color = 0;
+
+ texstate->filter0 |= i << 28;
+ size += 16;
+ state->count = i+1;
+ }
}
}
diff --git a/src/gallium/drivers/r300/r300_state_invariant.c b/src/gallium/drivers/r300/r300_state_invariant.c
deleted file mode 100644
index 34d3a169d5..0000000000
--- a/src/gallium/drivers/r300/r300_state_invariant.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright 2009 Joakim Sindholt <opensource@zhasha.com>
- * Corbin Simpson <MostAwesomeDude@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE. */
-
-#include "r300_context.h"
-#include "r300_cs.h"
-#include "r300_reg.h"
-#include "r300_screen.h"
-#include "r300_state_invariant.h"
-
-/* Calculate and emit invariant state. This is data that the 3D engine
- * will probably want at the beginning of every CS, but it's not currently
- * handled by any CSO setup, and in addition it doesn't really change much.
- *
- * Note that eventually this should be empty, but it's useful for development
- * and general unduplication of code. */
-void r300_emit_invariant_state(struct r300_context* r300,
- unsigned size, void* state)
-{
- CS_LOCALS(r300);
-
- if (r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0)) {
- /* Subpixel multisampling for AA. */
- BEGIN_CS(4);
- OUT_CS_REG(R300_GB_MSPOS0, 0x66666666);
- OUT_CS_REG(R300_GB_MSPOS1, 0x6666666);
- END_CS;
- }
-
- BEGIN_CS(12 + (r300->screen->caps.has_tcl ? 2 : 0));
-
- /*** Graphics Backend (GB) ***/
- /* Source of fog depth */
- OUT_CS_REG(R300_GB_SELECT, R300_GB_FOG_SELECT_1_1_W);
-
- /*** Fog (FG) ***/
- OUT_CS_REG(R300_FG_FOG_BLEND, 0x0);
- OUT_CS_REG(R300_FG_FOG_COLOR_R, 0x0);
- OUT_CS_REG(R300_FG_FOG_COLOR_G, 0x0);
- OUT_CS_REG(R300_FG_FOG_COLOR_B, 0x0);
-
- /*** VAP ***/
- /* Sign/normalize control */
- OUT_CS_REG(R300_VAP_PSC_SGN_NORM_CNTL, R300_SGN_NORM_NO_ZERO);
- /* TCL-only stuff */
- if (r300->screen->caps.has_tcl) {
- /* Amount of time to wait for vertex fetches in PVS */
- OUT_CS_REG(VAP_PVS_VTX_TIMEOUT_REG, 0xffff);
- }
-
- END_CS;
-
- /* XXX unsorted stuff from surface_fill */
- BEGIN_CS(38 + (r300->screen->caps.has_tcl ? 7 : 0) +
- (r300->screen->caps.is_rv350 ? 4 : 0));
-
- if (r300->screen->caps.has_tcl) {
- /*Flushing PVS is required before the VAP_GB registers can be changed*/
- OUT_CS_REG(R300_VAP_PVS_STATE_FLUSH_REG, 0);
- OUT_CS_REG_SEQ(R300_VAP_GB_VERT_CLIP_ADJ, 4);
- OUT_CS_32F(1.0);
- OUT_CS_32F(1.0);
- OUT_CS_32F(1.0);
- OUT_CS_32F(1.0);
- }
- /* XXX line tex stuffing */
- OUT_CS_REG_SEQ(R300_GA_LINE_S0, 1);
- OUT_CS_32F(0.0);
- OUT_CS_REG_SEQ(R300_GA_LINE_S1, 1);
- OUT_CS_32F(1.0);
- OUT_CS_REG(R300_GA_TRIANGLE_STIPPLE, 0x5 |
- (0x5 << R300_GA_TRIANGLE_STIPPLE_Y_SHIFT_SHIFT));
- /* XXX this big chunk should be refactored into rs_state */
- OUT_CS_REG(R300_GA_SOLID_RG, 0x00000000);
- OUT_CS_REG(R300_GA_SOLID_BA, 0x00000000);
- OUT_CS_REG(R300_GA_ROUND_MODE, 0x00000001);
- OUT_CS_REG(R300_GA_OFFSET, 0x00000000);
- OUT_CS_REG(R300_GA_FOG_SCALE, 0x3DBF1412);
- OUT_CS_REG(R300_GA_FOG_OFFSET, 0x00000000);
- OUT_CS_REG(R300_SU_TEX_WRAP, 0x00000000);
- OUT_CS_REG(R300_SU_DEPTH_SCALE, 0x4B7FFFFF);
- OUT_CS_REG(R300_SU_DEPTH_OFFSET, 0x00000000);
- OUT_CS_REG(R300_SC_HYPERZ, 0x0000001C);
- OUT_CS_REG(R300_SC_EDGERULE, 0x2DA49525);
- OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, 0x00000000);
-
- if (r300->screen->caps.is_rv350) {
- OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD, 0x01010101);
- OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD, 0xFEFEFEFE);
- }
-
- OUT_CS_REG(R300_ZB_BW_CNTL, 0x00000000);
- OUT_CS_REG(R300_ZB_DEPTHCLEARVALUE, 0x00000000);
- OUT_CS_REG(R300_ZB_HIZ_OFFSET, 0x00000000);
- OUT_CS_REG(R300_ZB_HIZ_PITCH, 0x00000000);
- END_CS;
-}
diff --git a/src/gallium/drivers/r300/r300_state_invariant.h b/src/gallium/drivers/r300/r300_state_invariant.h
deleted file mode 100644
index 83d031c7fe..0000000000
--- a/src/gallium/drivers/r300/r300_state_invariant.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE. */
-
-#ifndef R300_STATE_INVARIANT_H
-#define R300_STATE_INVARIANT_H
-
-struct r300_context;
-
-void r300_emit_invariant_state(struct r300_context* r300,
- unsigned size, void* state);
-
-#endif /* R300_STATE_INVARIANT_H */
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c
index 5a013e2a25..6206570fca 100644
--- a/src/gallium/drivers/r300/r300_texture.c
+++ b/src/gallium/drivers/r300/r300_texture.c
@@ -21,30 +21,28 @@
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE. */
-#include "pipe/p_screen.h"
-
-#include "util/u_format.h"
-#include "util/u_format_s3tc.h"
-#include "util/u_math.h"
-#include "util/u_memory.h"
+/* Always include headers in the reverse order!! ~ M. */
+#include "r300_texture.h"
#include "r300_context.h"
#include "r300_reg.h"
-#include "r300_texture.h"
#include "r300_transfer.h"
#include "r300_screen.h"
#include "r300_winsys.h"
-#define TILE_WIDTH 0
-#define TILE_HEIGHT 1
+#include "util/u_format.h"
+#include "util/u_format_s3tc.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "pipe/p_screen.h"
-static const unsigned microblock_table[5][3][2] = {
- /*linear tiled square-tiled */
- {{32, 1}, {8, 4}, {0, 0}}, /* 8 bits per pixel */
- {{16, 1}, {8, 2}, {4, 4}}, /* 16 bits per pixel */
- {{ 8, 1}, {4, 2}, {0, 0}}, /* 32 bits per pixel */
- {{ 4, 1}, {0, 0}, {2, 2}}, /* 64 bits per pixel */
- {{ 2, 1}, {0, 0}, {0, 0}} /* 128 bits per pixel */
+/* XXX NO! just no! */
+#include "state_tracker/drm_driver.h"
+
+enum r300_dim {
+ DIM_WIDTH = 0,
+ DIM_HEIGHT = 1
};
unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format,
@@ -596,21 +594,21 @@ static void r300_texture_setup_fb_state(struct r300_screen* screen,
/* Set framebuffer state. */
if (util_format_is_depth_or_stencil(tex->b.b.format)) {
for (i = 0; i <= tex->b.b.last_level; i++) {
- tex->fb_state.depthpitch[i] =
+ tex->fb_state.pitch[i] =
tex->hwpitch[i] |
R300_DEPTHMACROTILE(tex->mip_macrotile[i]) |
R300_DEPTHMICROTILE(tex->microtile);
}
- tex->fb_state.zb_format = r300_translate_zsformat(tex->b.b.format);
+ tex->fb_state.format = r300_translate_zsformat(tex->b.b.format);
} else {
for (i = 0; i <= tex->b.b.last_level; i++) {
- tex->fb_state.colorpitch[i] =
+ tex->fb_state.pitch[i] =
tex->hwpitch[i] |
r300_translate_colorformat(tex->b.b.format) |
R300_COLOR_TILE(tex->mip_macrotile[i]) |
R300_COLOR_MICROTILE(tex->microtile);
}
- tex->fb_state.us_out_fmt = r300_translate_out_fmt(tex->b.b.format);
+ tex->fb_state.format = r300_translate_out_fmt(tex->b.b.format);
}
}
@@ -620,8 +618,10 @@ void r300_texture_reinterpret_format(struct pipe_screen *screen,
{
struct r300_screen *r300screen = r300_screen(screen);
- SCREEN_DBG(r300screen, DBG_TEX, "r300: texture_reinterpret_format: %s -> %s\n",
- util_format_short_name(tex->format), util_format_short_name(new_format));
+ SCREEN_DBG(r300screen, DBG_TEX,
+ "r300: texture_reinterpret_format: %s -> %s\n",
+ util_format_short_name(tex->format),
+ util_format_short_name(new_format));
tex->format = new_format;
@@ -648,36 +648,65 @@ unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level,
}
}
-/**
- * Return the width (dim==TILE_WIDTH) or height (dim==TILE_HEIGHT) of one tile
- * of the given texture.
- */
-static unsigned r300_texture_get_tile_size(struct r300_texture* tex,
- int dim, boolean macrotile)
+/* Returns the number of pixels that the texture should be aligned to
+ * in the given dimension. */
+static unsigned r300_get_pixel_alignment(struct r300_texture *tex,
+ enum r300_buffer_tiling macrotile,
+ enum r300_dim dim)
{
- unsigned pixsize, tile_size;
-
- pixsize = util_format_get_blocksize(tex->b.b.format);
- tile_size = microblock_table[util_logbase2(pixsize)][tex->microtile][dim];
-
- if (macrotile) {
- tile_size *= 8;
+ static const unsigned table[2][5][3][2] =
+ {
+ {
+ /* Macro: linear linear linear
+ Micro: linear tiled square-tiled */
+ {{ 32, 1}, { 8, 4}, { 0, 0}}, /* 8 bits per pixel */
+ {{ 16, 1}, { 8, 2}, { 4, 4}}, /* 16 bits per pixel */
+ {{ 8, 1}, { 4, 2}, { 0, 0}}, /* 32 bits per pixel */
+ {{ 4, 1}, { 0, 0}, { 2, 2}}, /* 64 bits per pixel */
+ {{ 2, 1}, { 0, 0}, { 0, 0}} /* 128 bits per pixel */
+ },
+ {
+ /* Macro: tiled tiled tiled
+ Micro: linear tiled square-tiled */
+ {{256, 8}, {64, 32}, { 0, 0}}, /* 8 bits per pixel */
+ {{128, 8}, {64, 16}, {32, 32}}, /* 16 bits per pixel */
+ {{ 64, 8}, {32, 16}, { 0, 0}}, /* 32 bits per pixel */
+ {{ 32, 8}, { 0, 0}, {16, 16}}, /* 64 bits per pixel */
+ {{ 16, 8}, { 0, 0}, { 0, 0}} /* 128 bits per pixel */
+ }
+ };
+ static const unsigned aa_block[2] = {4, 8};
+ unsigned res = 0;
+ unsigned pixsize = util_format_get_blocksize(tex->b.b.format);
+
+ assert(macrotile <= R300_BUFFER_TILED);
+ assert(tex->microtile <= R300_BUFFER_SQUARETILED);
+ assert(pixsize <= 16);
+ assert(dim <= DIM_HEIGHT);
+
+ if (tex->b.b.nr_samples > 1) {
+ /* Multisampled textures have their own alignment scheme. */
+ if (pixsize == 4)
+ res = aa_block[dim];
+ } else {
+ /* Standard alignment. */
+ res = table[macrotile][util_logbase2(pixsize)][tex->microtile][dim];
}
- assert(tile_size);
- return tile_size;
+ assert(res);
+ return res;
}
/* Return true if macrotiling should be enabled on the miplevel. */
static boolean r300_texture_macro_switch(struct r300_texture *tex,
unsigned level,
boolean rv350_mode,
- int dim)
+ enum r300_dim dim)
{
unsigned tile, texdim;
- tile = r300_texture_get_tile_size(tex, dim, TRUE);
- if (dim == TILE_WIDTH) {
+ tile = r300_get_pixel_alignment(tex, R300_BUFFER_TILED, dim);
+ if (dim == DIM_WIDTH) {
texdim = u_minify(tex->b.b.width0, level);
} else {
texdim = u_minify(tex->b.b.height0, level);
@@ -713,8 +742,8 @@ unsigned r300_texture_get_stride(struct r300_screen* screen,
width = u_minify(tex->b.b.width0, level);
if (util_format_is_plain(tex->b.b.format)) {
- tile_width = r300_texture_get_tile_size(tex, TILE_WIDTH,
- tex->mip_macrotile[level]);
+ tile_width = r300_get_pixel_alignment(tex, tex->mip_macrotile[level],
+ DIM_WIDTH);
width = align(width, tile_width);
stride = util_format_get_stride(tex->b.b.format, width);
@@ -743,8 +772,8 @@ static unsigned r300_texture_get_nblocksy(struct r300_texture* tex,
height = u_minify(tex->b.b.height0, level);
if (util_format_is_plain(tex->b.b.format)) {
- tile_height = r300_texture_get_tile_size(tex, TILE_HEIGHT,
- tex->mip_macrotile[level]);
+ tile_height = r300_get_pixel_alignment(tex, tex->mip_macrotile[level],
+ DIM_HEIGHT);
height = align(height, tile_height);
/* This is needed for the kernel checker, unfortunately. */
@@ -784,21 +813,26 @@ static void r300_setup_miptree(struct r300_screen* screen,
unsigned stride, size, layer_size, nblocksy, i;
boolean rv350_mode = screen->caps.is_rv350;
- SCREEN_DBG(screen, DBG_TEXALLOC, "r300: Making miptree for texture, format %s\n",
- util_format_short_name(base->format));
+ SCREEN_DBG(screen, DBG_TEXALLOC,
+ "r300: Making miptree for texture, format %s\n",
+ util_format_short_name(base->format));
for (i = 0; i <= base->last_level; i++) {
/* Let's see if this miplevel can be macrotiled. */
tex->mip_macrotile[i] =
(tex->macrotile == R300_BUFFER_TILED &&
- r300_texture_macro_switch(tex, i, rv350_mode, TILE_WIDTH) &&
- r300_texture_macro_switch(tex, i, rv350_mode, TILE_HEIGHT)) ?
+ r300_texture_macro_switch(tex, i, rv350_mode, DIM_WIDTH) &&
+ r300_texture_macro_switch(tex, i, rv350_mode, DIM_HEIGHT)) ?
R300_BUFFER_TILED : R300_BUFFER_LINEAR;
stride = r300_texture_get_stride(screen, tex, i);
nblocksy = r300_texture_get_nblocksy(tex, i);
layer_size = stride * nblocksy;
+ if (base->nr_samples) {
+ layer_size *= base->nr_samples;
+ }
+
if (base->target == PIPE_TEXTURE_CUBE)
size = layer_size * 6;
else
@@ -864,8 +898,8 @@ static void r300_setup_tiling(struct pipe_screen *screen,
}
/* Set macrotiling. */
- if (r300_texture_macro_switch(tex, 0, rv350_mode, TILE_WIDTH) &&
- r300_texture_macro_switch(tex, 0, rv350_mode, TILE_HEIGHT)) {
+ if (r300_texture_macro_switch(tex, 0, rv350_mode, DIM_WIDTH) &&
+ r300_texture_macro_switch(tex, 0, rv350_mode, DIM_HEIGHT)) {
tex->macrotile = R300_BUFFER_TILED;
}
}
@@ -899,17 +933,14 @@ static boolean r300_texture_get_handle(struct pipe_screen* screen,
{
struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys;
struct r300_texture* tex = (struct r300_texture*)texture;
- unsigned stride;
if (!tex) {
return FALSE;
}
- stride = r300_texture_get_stride(r300_screen(screen), tex, 0);
-
- rws->buffer_get_handle(rws, tex->buffer, stride, whandle);
+ whandle->stride = r300_texture_get_stride(r300_screen(screen), tex, 0);
- return TRUE;
+ return rws->buffer_get_handle(rws, tex->buffer, whandle);
}
struct u_resource_vtbl r300_texture_vtbl =
@@ -966,11 +997,12 @@ struct pipe_resource* r300_texture_create(struct pipe_screen* screen,
SCREEN_DBG(rscreen, DBG_TEX,
"r300: texture_create: Macro: %s, Micro: %s, Pitch: %i, "
- "Dim: %ix%ix%i, LastLevel: %i, Format: %s\n",
+ "Dim: %ix%ix%i, LastLevel: %i, Size: %i, Format: %s\n",
tex->macrotile ? "YES" : " NO",
tex->microtile ? "YES" : " NO",
tex->hwpitch[0],
base->width0, base->height0, base->depth0, base->last_level,
+ tex->size,
util_format_short_name(base->format));
tex->domain = base->flags & R300_RESOURCE_FLAG_TRANSFER ? R300_DOMAIN_GTT :
@@ -979,16 +1011,16 @@ struct pipe_resource* r300_texture_create(struct pipe_screen* screen,
tex->buffer = rws->buffer_create(rws, 2048, base->bind, tex->domain,
tex->size);
+ if (!tex->buffer) {
+ FREE(tex);
+ return NULL;
+ }
+
rws->buffer_set_tiling(rws, tex->buffer,
tex->pitch[0] * util_format_get_blocksize(tex->b.b.format),
tex->microtile,
tex->macrotile);
- if (!tex->buffer) {
- FREE(tex);
- return NULL;
- }
-
return (struct pipe_resource*)tex;
}
@@ -1002,26 +1034,27 @@ struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen,
unsigned flags)
{
struct r300_texture* tex = r300_texture(texture);
- struct pipe_surface* surface = CALLOC_STRUCT(pipe_surface);
- unsigned offset;
-
- offset = r300_texture_get_offset(tex, level, zslice, face);
+ struct r300_surface* surface = CALLOC_STRUCT(r300_surface);
if (surface) {
- pipe_reference_init(&surface->reference, 1);
- pipe_resource_reference(&surface->texture, texture);
- surface->format = texture->format;
- surface->width = u_minify(texture->width0, level);
- surface->height = u_minify(texture->height0, level);
- surface->offset = offset;
- surface->usage = flags;
- surface->zslice = zslice;
- surface->texture = texture;
- surface->face = face;
- surface->level = level;
+ pipe_reference_init(&surface->base.reference, 1);
+ pipe_resource_reference(&surface->base.texture, texture);
+ surface->base.format = texture->format;
+ surface->base.width = u_minify(texture->width0, level);
+ surface->base.height = u_minify(texture->height0, level);
+ surface->base.usage = flags;
+ surface->base.zslice = zslice;
+ surface->base.face = face;
+ surface->base.level = level;
+
+ surface->buffer = tex->buffer;
+ surface->domain = tex->domain;
+ surface->offset = r300_texture_get_offset(tex, level, zslice, face);
+ surface->pitch = tex->fb_state.pitch[level];
+ surface->format = tex->fb_state.format;
}
- return surface;
+ return &surface->base;
}
/* Not required to implement u_resource_vtbl, consider moving to another file:
@@ -1041,7 +1074,6 @@ r300_texture_from_handle(struct pipe_screen* screen,
struct r300_screen* rscreen = r300_screen(screen);
struct r300_winsys_buffer *buffer;
struct r300_texture* tex;
- unsigned stride;
boolean override_zb_flags;
/* Support only 2D textures without mipmaps */
@@ -1051,7 +1083,8 @@ r300_texture_from_handle(struct pipe_screen* screen,
return NULL;
}
- buffer = rws->buffer_from_handle(rws, screen, whandle, &stride);
+ /* XXX make the winsys return the stride_override, see i915_resource_texture.c:830 */
+ buffer = rws->buffer_from_handle(rws, whandle->handle);
if (!buffer) {
return NULL;
}
@@ -1067,7 +1100,7 @@ r300_texture_from_handle(struct pipe_screen* screen,
tex->b.b.screen = screen;
tex->domain = R300_DOMAIN_VRAM;
- tex->stride_override = stride;
+ tex->stride_override = whandle->stride;
/* one ref already taken */
tex->buffer = buffer;
@@ -1079,7 +1112,7 @@ r300_texture_from_handle(struct pipe_screen* screen,
"Pitch: % 4i, Dim: %ix%i, Format: %s\n",
tex->macrotile ? "YES" : " NO",
tex->microtile ? "YES" : " NO",
- stride / util_format_get_blocksize(base->format),
+ whandle->stride / util_format_get_blocksize(base->format),
base->width0, base->height0,
util_format_short_name(base->format));
diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h
index ff640c56ee..99e7694254 100644
--- a/src/gallium/drivers/r300/r300_texture.h
+++ b/src/gallium/drivers/r300/r300_texture.h
@@ -23,8 +23,11 @@
#ifndef R300_TEXTURE_H
#define R300_TEXTURE_H
-#include "util/u_format.h"
+#include "pipe/p_format.h"
+struct pipe_screen;
+struct pipe_resource;
+struct winsys_handle;
struct r300_texture;
struct r300_screen;
diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.c b/src/gallium/drivers/r300/r300_tgsi_to_rc.c
index 89f39af976..5394e04f72 100644
--- a/src/gallium/drivers/r300/r300_tgsi_to_rc.c
+++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.c
@@ -105,12 +105,12 @@ static unsigned translate_opcode(unsigned opcode)
/* case TGSI_OPCODE_DIV: return RC_OPCODE_DIV; */
/* case TGSI_OPCODE_DP2: return RC_OPCODE_DP2; */
case TGSI_OPCODE_TXL: return RC_OPCODE_TXL;
- /* case TGSI_OPCODE_BRK: return RC_OPCODE_BRK; */
+ case TGSI_OPCODE_BRK: return RC_OPCODE_BRK;
case TGSI_OPCODE_IF: return RC_OPCODE_IF;
- /* case TGSI_OPCODE_LOOP: return RC_OPCODE_LOOP; */
+ case TGSI_OPCODE_BGNLOOP: return RC_OPCODE_BGNLOOP;
case TGSI_OPCODE_ELSE: return RC_OPCODE_ELSE;
case TGSI_OPCODE_ENDIF: return RC_OPCODE_ENDIF;
- /* case TGSI_OPCODE_ENDLOOP: return RC_OPCODE_ENDLOOP; */
+ case TGSI_OPCODE_ENDLOOP: return RC_OPCODE_ENDLOOP;
/* case TGSI_OPCODE_PUSHA: return RC_OPCODE_PUSHA; */
/* case TGSI_OPCODE_POPA: return RC_OPCODE_POPA; */
case TGSI_OPCODE_CEIL: return RC_OPCODE_CEIL;
diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c
index 0d88d745c0..02421a58b8 100644
--- a/src/gallium/drivers/r300/r300_transfer.c
+++ b/src/gallium/drivers/r300/r300_transfer.c
@@ -57,22 +57,11 @@ static void r300_copy_from_tiled_texture(struct pipe_context *ctx,
subdst.face = 0;
subdst.level = 0;
- /* XXX if we don't flush before copying the texture and mapping it,
- * we get wrong pixels, i.e. it's like latest draw calls didn't happen,
- * including this blit. Tests: e.g. piglit/provoking-vertex
- *
- * Since the flush immediately before mapping is implicit (the buffer is
- * always referenced in resource_copy_region), every read transfer costs
- * 2 flushes. That sucks. */
- ctx->flush(ctx, 0, NULL);
-
ctx->resource_copy_region(ctx, &r300transfer->detiled_texture->b.b, subdst,
0, 0, 0,
tex, transfer->sr,
transfer->box.x, transfer->box.y, transfer->box.z,
transfer->box.width, transfer->box.height);
-
- /* Flushing after the copy is implicit, issued by winsys. */
}
/* Copy a detiled texture to a tiled one. */
@@ -92,7 +81,6 @@ static void r300_copy_into_tiled_texture(struct pipe_context *ctx,
0, 0, 0,
transfer->box.width, transfer->box.height);
- /* XXX this flush fixes a few piglit tests (e.g. glean/pixelFormats). */
ctx->flush(ctx, 0, NULL);
}
@@ -107,7 +95,7 @@ r300_texture_get_transfer(struct pipe_context *ctx,
struct r300_screen *r300screen = r300_screen(ctx->screen);
struct r300_transfer *trans;
struct pipe_resource base;
- boolean referenced_cs, referenced_hw;
+ boolean referenced_cs, referenced_hw, blittable;
referenced_cs = r300screen->rws->is_buffer_referenced(
r300screen->rws, tex->buffer, R300_REF_CS);
@@ -118,6 +106,10 @@ r300_texture_get_transfer(struct pipe_context *ctx,
r300screen->rws, tex->buffer, R300_REF_HW);
}
+ blittable = ctx->screen->is_format_supported(
+ ctx->screen, texture->format, texture->target, 0,
+ PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET, 0);
+
trans = CALLOC_STRUCT(r300_transfer);
if (trans) {
/* Initialize the transfer object. */
@@ -130,7 +122,7 @@ r300_texture_get_transfer(struct pipe_context *ctx,
* for this transfer.
* Also make write transfers pipelined. */
if (tex->microtile || tex->macrotile ||
- (referenced_hw & !(usage & PIPE_TRANSFER_READ))) {
+ ((referenced_hw & !(usage & PIPE_TRANSFER_READ)) && blittable)) {
base.target = PIPE_TEXTURE_2D;
base.format = texture->format;
base.width0 = box->width;
@@ -158,6 +150,30 @@ r300_texture_get_transfer(struct pipe_context *ctx,
ctx->screen->resource_create(ctx->screen,
&base));
+ if (!trans->detiled_texture) {
+ /* Oh crap, the thing can't create the texture.
+ * Let's flush and try again. */
+ ctx->flush(ctx, 0, NULL);
+
+ trans->detiled_texture = r300_texture(
+ ctx->screen->resource_create(ctx->screen,
+ &base));
+
+ if (!trans->detiled_texture) {
+ /* For linear textures, it's safe to fallback to
+ * an unpipelined transfer. */
+ if (!tex->microtile && !tex->macrotile) {
+ goto unpipelined;
+ }
+
+ /* Otherwise, go to hell. */
+ fprintf(stderr,
+ "r300: Failed to create a transfer object, praise.\n");
+ FREE(trans);
+ return NULL;
+ }
+ }
+
assert(!trans->detiled_texture->microtile &&
!trans->detiled_texture->macrotile);
@@ -179,16 +195,20 @@ r300_texture_get_transfer(struct pipe_context *ctx,
/* Always referenced in the blit. */
ctx->flush(ctx, 0, NULL);
}
- } else {
- trans->transfer.stride =
+ return &trans->transfer;
+ }
+
+ unpipelined:
+ /* Unpipelined transfer. */
+ trans->transfer.stride =
r300_texture_get_stride(r300screen, tex, sr.level);
- trans->offset = r300_texture_get_offset(tex, sr.level, box->z, sr.face);
+ trans->offset = r300_texture_get_offset(tex, sr.level, box->z, sr.face);
- if (referenced_cs && (usage & PIPE_TRANSFER_READ))
- ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL);
- }
+ if (referenced_cs && (usage & PIPE_TRANSFER_READ))
+ ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL);
+ return &trans->transfer;
}
- return &trans->transfer;
+ return NULL;
}
void r300_texture_transfer_destroy(struct pipe_context *ctx,
diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h
index 8a8888d481..3b5e9eec60 100644
--- a/src/gallium/drivers/r300/r300_winsys.h
+++ b/src/gallium/drivers/r300/r300_winsys.h
@@ -47,13 +47,6 @@ enum r300_reference_domain { /* bitfield */
R300_REF_HW = 2
};
-struct r300_cs_info {
- /* In DWORDs. */
- unsigned used;
- unsigned free;
- unsigned capacity;
-};
-
struct r300_winsys_screen {
void (*destroy)(struct r300_winsys_screen *ws);
@@ -109,16 +102,13 @@ struct r300_winsys_screen {
* Returns TRUE if a flush is required. */
boolean (*validate)(struct r300_winsys_screen* winsys);
- /* Return current CS info. */
- void (*get_cs_info)(struct r300_winsys_screen *winsys,
- struct r300_cs_info *info);
+ /* Return the number of free dwords in CS. */
+ unsigned (*get_cs_free_dwords)(struct r300_winsys_screen *winsys);
- /* Start a command emit. */
- void (*begin_cs)(struct r300_winsys_screen* winsys,
- int size,
- const char* file,
- const char* function,
- int line);
+ /* Return the pointer to the first free dword in CS and assume a pipe
+ * driver wants to fill "count" dwords. */
+ uint32_t *(*get_cs_pointer)(struct r300_winsys_screen *winsys,
+ unsigned count);
/* Write a dword to the command buffer. */
void (*write_cs_dword)(struct r300_winsys_screen* winsys, uint32_t dword);
@@ -134,12 +124,6 @@ struct r300_winsys_screen {
enum r300_buffer_domain wd,
uint32_t flags);
- /* Finish a command emit. */
- void (*end_cs)(struct r300_winsys_screen* winsys,
- const char* file,
- const char* function,
- int line);
-
/* Flush the CS. */
void (*flush_cs)(struct r300_winsys_screen* winsys);
@@ -164,12 +148,10 @@ struct r300_winsys_screen {
enum r300_value_id vid);
struct r300_winsys_buffer *(*buffer_from_handle)(struct r300_winsys_screen *winsys,
- struct pipe_screen *screen,
- struct winsys_handle *whandle,
- unsigned *stride);
+ unsigned handle);
+
boolean (*buffer_get_handle)(struct r300_winsys_screen *winsys,
struct r300_winsys_buffer *buffer,
- unsigned stride,
struct winsys_handle *whandle);
boolean (*is_buffer_referenced)(struct r300_winsys_screen *winsys,
diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c
index 80c3069cf5..1dcb19babc 100644
--- a/src/gallium/drivers/r600/r600_blit.c
+++ b/src/gallium/drivers/r600/r600_blit.c
@@ -49,6 +49,9 @@ static void r600_blitter_save_states(struct r600_context *rctx)
rctx->vertex_elements);
util_blitter_save_viewport(rctx->blitter,
&rctx->viewport);
+ /* XXX util_blitter_save_clip(rctx->blitter, &rctx->clip); */
+ util_blitter_save_vertex_buffers(rctx->blitter, rctx->nvertex_buffer,
+ rctx->vertex_buffer);
}
static void r600_clear(struct pipe_context *ctx, unsigned buffers,
diff --git a/src/gallium/drivers/r600/r600_helper.c b/src/gallium/drivers/r600/r600_helper.c
index 9370a5355e..e3175b627a 100644
--- a/src/gallium/drivers/r600/r600_helper.c
+++ b/src/gallium/drivers/r600/r600_helper.c
@@ -26,7 +26,6 @@
#include <stdio.h>
#include <errno.h>
#include <util/u_inlines.h>
-#include <util/u_format.h>
#include "r600_screen.h"
#include "r600d.h"
diff --git a/src/gallium/drivers/r600/r600_query.c b/src/gallium/drivers/r600/r600_query.c
index 24746e7877..9b02ae680e 100644
--- a/src/gallium/drivers/r600/r600_query.c
+++ b/src/gallium/drivers/r600/r600_query.c
@@ -50,7 +50,7 @@ static void r600_end_query(struct pipe_context *pipe, struct pipe_query *query)
static boolean r600_get_query_result(struct pipe_context *pipe,
struct pipe_query *query,
- boolean wait, uint64_t *result)
+ boolean wait, void *result)
{
return TRUE;
}
diff --git a/src/gallium/drivers/rbug/rbug_context.c b/src/gallium/drivers/rbug/rbug_context.c
index 164d811ab4..00b167e256 100644
--- a/src/gallium/drivers/rbug/rbug_context.c
+++ b/src/gallium/drivers/rbug/rbug_context.c
@@ -241,7 +241,7 @@ static boolean
rbug_get_query_result(struct pipe_context *_pipe,
struct pipe_query *query,
boolean wait,
- uint64_t *result)
+ void *result)
{
struct rbug_context *rb_pipe = rbug_context(_pipe);
struct pipe_context *pipe = rb_pipe->pipe;
diff --git a/src/gallium/drivers/softpipe/Makefile b/src/gallium/drivers/softpipe/Makefile
index 83f3e4a19b..35d426aa3e 100644
--- a/src/gallium/drivers/softpipe/Makefile
+++ b/src/gallium/drivers/softpipe/Makefile
@@ -25,6 +25,7 @@ C_SOURCES = \
sp_state_derived.c \
sp_state_fs.c \
sp_state_sampler.c \
+ sp_state_so.c \
sp_state_rasterizer.c \
sp_state_surface.c \
sp_state_vertex.c \
diff --git a/src/gallium/drivers/softpipe/SConscript b/src/gallium/drivers/softpipe/SConscript
index b80c6dea93..be5917a688 100644
--- a/src/gallium/drivers/softpipe/SConscript
+++ b/src/gallium/drivers/softpipe/SConscript
@@ -27,6 +27,7 @@ softpipe = env.ConvenienceLibrary(
'sp_state_fs.c',
'sp_state_rasterizer.c',
'sp_state_sampler.c',
+ 'sp_state_so.c',
'sp_state_surface.c',
'sp_state_vertex.c',
'sp_surface.c',
diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c
index 2f10b46e98..12ef98aac7 100644
--- a/src/gallium/drivers/softpipe/sp_context.c
+++ b/src/gallium/drivers/softpipe/sp_context.c
@@ -114,6 +114,11 @@ softpipe_destroy( struct pipe_context *pipe )
pipe_sampler_view_reference(&softpipe->vertex_sampler_views[i], NULL);
}
+ for (i = 0; i < PIPE_MAX_GEOMETRY_SAMPLERS; i++) {
+ sp_destroy_tex_tile_cache(softpipe->geometry_tex_cache[i]);
+ pipe_sampler_view_reference(&softpipe->geometry_sampler_views[i], NULL);
+ }
+
for (i = 0; i < PIPE_SHADER_TYPES; i++) {
uint j;
@@ -174,7 +179,12 @@ softpipe_is_resource_referenced( struct pipe_context *pipe,
softpipe->vertex_tex_cache[i]->texture == texture)
return PIPE_REFERENCED_FOR_READ;
}
-
+ for (i = 0; i < PIPE_MAX_GEOMETRY_SAMPLERS; i++) {
+ if (softpipe->geometry_tex_cache[i] &&
+ softpipe->geometry_tex_cache[i]->texture == texture)
+ return PIPE_REFERENCED_FOR_READ;
+ }
+
return PIPE_UNREFERENCED;
}
@@ -225,6 +235,7 @@ softpipe_create_context( struct pipe_screen *screen,
softpipe->pipe.create_sampler_state = softpipe_create_sampler_state;
softpipe->pipe.bind_fragment_sampler_states = softpipe_bind_sampler_states;
softpipe->pipe.bind_vertex_sampler_states = softpipe_bind_vertex_sampler_states;
+ softpipe->pipe.bind_geometry_sampler_states = softpipe_bind_geometry_sampler_states;
softpipe->pipe.delete_sampler_state = softpipe_delete_sampler_state;
softpipe->pipe.create_depth_stencil_alpha_state = softpipe_create_depth_stencil_state;
@@ -251,6 +262,10 @@ softpipe_create_context( struct pipe_screen *screen,
softpipe->pipe.bind_vertex_elements_state = softpipe_bind_vertex_elements_state;
softpipe->pipe.delete_vertex_elements_state = softpipe_delete_vertex_elements_state;
+ softpipe->pipe.create_stream_output_state = softpipe_create_stream_output_state;
+ softpipe->pipe.bind_stream_output_state = softpipe_bind_stream_output_state;
+ softpipe->pipe.delete_stream_output_state = softpipe_delete_stream_output_state;
+
softpipe->pipe.set_blend_color = softpipe_set_blend_color;
softpipe->pipe.set_stencil_ref = softpipe_set_stencil_ref;
softpipe->pipe.set_clip_state = softpipe_set_clip_state;
@@ -261,10 +276,11 @@ softpipe_create_context( struct pipe_screen *screen,
softpipe->pipe.set_scissor_state = softpipe_set_scissor_state;
softpipe->pipe.set_fragment_sampler_views = softpipe_set_sampler_views;
softpipe->pipe.set_vertex_sampler_views = softpipe_set_vertex_sampler_views;
+ softpipe->pipe.set_geometry_sampler_views = softpipe_set_geometry_sampler_views;
softpipe->pipe.create_sampler_view = softpipe_create_sampler_view;
softpipe->pipe.sampler_view_destroy = softpipe_sampler_view_destroy;
softpipe->pipe.set_viewport_state = softpipe_set_viewport_state;
-
+ softpipe->pipe.set_stream_output_buffers = softpipe_set_stream_output_buffers;
softpipe->pipe.set_vertex_buffers = softpipe_set_vertex_buffers;
softpipe->pipe.draw_arrays = softpipe_draw_arrays;
@@ -272,6 +288,7 @@ softpipe_create_context( struct pipe_screen *screen,
softpipe->pipe.draw_range_elements = softpipe_draw_range_elements;
softpipe->pipe.draw_arrays_instanced = softpipe_draw_arrays_instanced;
softpipe->pipe.draw_elements_instanced = softpipe_draw_elements_instanced;
+ softpipe->pipe.draw_stream_output = softpipe_draw_stream_output;
softpipe->pipe.clear = softpipe_clear;
softpipe->pipe.flush = softpipe_flush;
@@ -296,6 +313,9 @@ softpipe_create_context( struct pipe_screen *screen,
for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) {
softpipe->vertex_tex_cache[i] = sp_create_tex_tile_cache( &softpipe->pipe );
}
+ for (i = 0; i < PIPE_MAX_GEOMETRY_SAMPLERS; i++) {
+ softpipe->geometry_tex_cache[i] = sp_create_tex_tile_cache( &softpipe->pipe );
+ }
softpipe->fs_machine = tgsi_exec_machine_create();
@@ -314,10 +334,17 @@ softpipe_create_context( struct pipe_screen *screen,
goto fail;
draw_texture_samplers(softpipe->draw,
+ PIPE_SHADER_VERTEX,
PIPE_MAX_VERTEX_SAMPLERS,
(struct tgsi_sampler **)
softpipe->tgsi.vert_samplers_list);
+ draw_texture_samplers(softpipe->draw,
+ PIPE_SHADER_GEOMETRY,
+ PIPE_MAX_GEOMETRY_SAMPLERS,
+ (struct tgsi_sampler **)
+ softpipe->tgsi.geom_samplers_list);
+
if (debug_get_bool_option( "SP_NO_RAST", FALSE ))
softpipe->no_rast = TRUE;
diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h
index b3d3fe620f..53115a827d 100644
--- a/src/gallium/drivers/softpipe/sp_context.h
+++ b/src/gallium/drivers/softpipe/sp_context.h
@@ -50,6 +50,7 @@ struct softpipe_tex_tile_cache;
struct sp_fragment_shader;
struct sp_vertex_shader;
struct sp_velems_state;
+struct sp_so_state;
struct softpipe_context {
@@ -59,12 +60,14 @@ struct softpipe_context {
struct pipe_blend_state *blend;
struct pipe_sampler_state *sampler[PIPE_MAX_SAMPLERS];
struct pipe_sampler_state *vertex_samplers[PIPE_MAX_VERTEX_SAMPLERS];
+ struct pipe_sampler_state *geometry_samplers[PIPE_MAX_GEOMETRY_SAMPLERS];
struct pipe_depth_stencil_alpha_state *depth_stencil;
struct pipe_rasterizer_state *rasterizer;
struct sp_fragment_shader *fs;
struct sp_vertex_shader *vs;
struct sp_geometry_shader *gs;
struct sp_velems_state *velems;
+ struct sp_so_state *so;
/** Other rendering state */
struct pipe_blend_color blend_color;
@@ -76,13 +79,23 @@ struct softpipe_context {
struct pipe_scissor_state scissor;
struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
struct pipe_sampler_view *vertex_sampler_views[PIPE_MAX_VERTEX_SAMPLERS];
+ struct pipe_sampler_view *geometry_sampler_views[PIPE_MAX_GEOMETRY_SAMPLERS];
struct pipe_viewport_state viewport;
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
+ struct {
+ struct softpipe_resource *buffer[PIPE_MAX_SO_BUFFERS];
+ int offset[PIPE_MAX_SO_BUFFERS];
+ int so_count[PIPE_MAX_SO_BUFFERS];
+ int num_buffers;
+ } so_target;
+ struct pipe_query_data_so_statistics so_stats;
unsigned num_samplers;
unsigned num_sampler_views;
unsigned num_vertex_samplers;
unsigned num_vertex_sampler_views;
+ unsigned num_geometry_samplers;
+ unsigned num_geometry_sampler_views;
unsigned num_vertex_buffers;
unsigned dirty; /**< Mask of SP_NEW_x flags */
@@ -139,6 +152,7 @@ struct softpipe_context {
/** TGSI exec things */
struct {
+ struct sp_sampler_varient *geom_samplers_list[PIPE_MAX_GEOMETRY_SAMPLERS];
struct sp_sampler_varient *vert_samplers_list[PIPE_MAX_VERTEX_SAMPLERS];
struct sp_sampler_varient *frag_samplers_list[PIPE_MAX_SAMPLERS];
} tgsi;
@@ -160,6 +174,7 @@ struct softpipe_context {
unsigned tex_timestamp;
struct softpipe_tex_tile_cache *tex_cache[PIPE_MAX_SAMPLERS];
struct softpipe_tex_tile_cache *vertex_tex_cache[PIPE_MAX_VERTEX_SAMPLERS];
+ struct softpipe_tex_tile_cache *geometry_tex_cache[PIPE_MAX_GEOMETRY_SAMPLERS];
unsigned use_sse : 1;
unsigned dump_fs : 1;
diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c
index b30036e230..79daa68f3b 100644
--- a/src/gallium/drivers/softpipe/sp_draw_arrays.c
+++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c
@@ -84,6 +84,57 @@ softpipe_draw_arrays(struct pipe_context *pipe, unsigned mode,
1);
}
+void
+softpipe_draw_stream_output(struct pipe_context *pipe, unsigned mode)
+{
+ struct softpipe_context *sp = softpipe_context(pipe);
+ struct draw_context *draw = sp->draw;
+ const unsigned start = 0;
+ const unsigned count = sp->so_target.so_count[0];
+ void *buf = sp->so_target.buffer[0]->data;
+ int offset = sp->so_target.offset[0];
+
+ if (!softpipe_check_render_cond(sp) ||
+ sp->so_target.num_buffers != 1)
+ return;
+
+ sp->reduced_api_prim = u_reduced_prim(mode);
+
+ if (sp->dirty) {
+ softpipe_update_derived(sp);
+ }
+
+ softpipe_map_transfers(sp);
+
+ /* Map so buffers */
+ if (offset < 0) /* we were appending so start from beginning */
+ offset = 0;
+ buf = (void*)((int32_t*)buf + offset);
+ draw_set_mapped_vertex_buffer(draw, 0, buf);
+
+ draw_set_mapped_element_buffer_range(draw,
+ 0, 0,
+ start,
+ start + count - 1,
+ NULL);
+
+ /* draw! */
+ draw_arrays_instanced(draw, mode, start, count, 0, 1);
+
+ /* unmap vertex/index buffers - will cause draw module to flush */
+ draw_set_mapped_vertex_buffer(draw, 0, NULL);
+
+ /*
+ * TODO: Flush only when a user vertex/index buffer is present
+ * (or even better, modify draw module to do this
+ * internally when this condition is seen?)
+ */
+ draw_flush(draw);
+
+ /* Note: leave drawing surfaces mapped */
+ sp->dirty_render_cache = TRUE;
+}
+
void
softpipe_draw_range_elements(struct pipe_context *pipe,
diff --git a/src/gallium/drivers/softpipe/sp_flush.c b/src/gallium/drivers/softpipe/sp_flush.c
index 5024fc8a81..4a53ef048f 100644
--- a/src/gallium/drivers/softpipe/sp_flush.c
+++ b/src/gallium/drivers/softpipe/sp_flush.c
@@ -56,6 +56,9 @@ softpipe_flush( struct pipe_context *pipe,
for (i = 0; i < softpipe->num_vertex_sampler_views; i++) {
sp_flush_tex_tile_cache(softpipe->vertex_tex_cache[i]);
}
+ for (i = 0; i < softpipe->num_geometry_sampler_views; i++) {
+ sp_flush_tex_tile_cache(softpipe->geometry_tex_cache[i]);
+ }
}
if (flags & PIPE_FLUSH_SWAPBUFFERS) {
diff --git a/src/gallium/drivers/softpipe/sp_prim_vbuf.c b/src/gallium/drivers/softpipe/sp_prim_vbuf.c
index db0d175510..c60249dbfb 100644
--- a/src/gallium/drivers/softpipe/sp_prim_vbuf.c
+++ b/src/gallium/drivers/softpipe/sp_prim_vbuf.c
@@ -542,6 +542,22 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
}
}
+static void
+sp_vbuf_so_info(struct vbuf_render *vbr, uint primitives, uint vertices)
+{
+ struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
+ struct softpipe_context *softpipe = cvbr->softpipe;
+ unsigned i;
+
+ for (i = 0; i < softpipe->so_target.num_buffers; ++i) {
+ softpipe->so_target.so_count[i] += vertices;
+ }
+
+ softpipe->so_stats.num_primitives_written = primitives;
+ softpipe->so_stats.primitives_storage_needed =
+ vertices * 4 /*sizeof(float|int32)*/ * 4 /*x,y,z,w*/;
+}
+
static void
sp_vbuf_destroy(struct vbuf_render *vbr)
@@ -575,6 +591,7 @@ sp_create_vbuf_backend(struct softpipe_context *sp)
cvbr->base.draw_elements = sp_vbuf_draw_elements;
cvbr->base.draw_arrays = sp_vbuf_draw_arrays;
cvbr->base.release_vertices = sp_vbuf_release_vertices;
+ cvbr->base.set_stream_output_info = sp_vbuf_so_info;
cvbr->base.destroy = sp_vbuf_destroy;
cvbr->softpipe = sp;
diff --git a/src/gallium/drivers/softpipe/sp_quad_fs.c b/src/gallium/drivers/softpipe/sp_quad_fs.c
index 907e94b59b..d240bcbf3b 100644
--- a/src/gallium/drivers/softpipe/sp_quad_fs.c
+++ b/src/gallium/drivers/softpipe/sp_quad_fs.c
@@ -109,7 +109,7 @@ shade_quads(struct quad_stage *qs,
{
struct softpipe_context *softpipe = qs->softpipe;
struct tgsi_exec_machine *machine = softpipe->fs_machine;
- unsigned i, pass = 0;
+ unsigned i, nr_quads = 0;
for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) {
machine->Consts[i] = softpipe->mapped_constants[PIPE_SHADER_FRAGMENT][i];
@@ -123,11 +123,11 @@ shade_quads(struct quad_stage *qs,
if (/*do_coverage*/ 0)
coverage_quad( qs, quads[i] );
- quads[pass++] = quads[i];
+ quads[nr_quads++] = quads[i];
}
- if (pass)
- qs->next->run(qs->next, quads, pass);
+ if (nr_quads)
+ qs->next->run(qs->next, quads, nr_quads);
}
diff --git a/src/gallium/drivers/softpipe/sp_query.c b/src/gallium/drivers/softpipe/sp_query.c
index b959af63af..4ae69c1c2b 100644
--- a/src/gallium/drivers/softpipe/sp_query.c
+++ b/src/gallium/drivers/softpipe/sp_query.c
@@ -41,6 +41,7 @@ struct softpipe_query {
unsigned type;
uint64_t start;
uint64_t end;
+ struct pipe_query_data_so_statistics so;
};
@@ -55,7 +56,11 @@ softpipe_create_query(struct pipe_context *pipe,
{
struct softpipe_query* sq;
- assert(type == PIPE_QUERY_OCCLUSION_COUNTER || type == PIPE_QUERY_TIME_ELAPSED);
+ assert(type == PIPE_QUERY_OCCLUSION_COUNTER ||
+ type == PIPE_QUERY_TIME_ELAPSED ||
+ type == PIPE_QUERY_SO_STATISTICS ||
+ type == PIPE_QUERY_GPU_FINISHED ||
+ type == PIPE_QUERY_TIMESTAMP_DISJOINT);
sq = CALLOC_STRUCT( softpipe_query );
sq->type = type;
@@ -75,7 +80,7 @@ softpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
{
struct softpipe_context *softpipe = softpipe_context( pipe );
struct softpipe_query *sq = softpipe_query(q);
-
+
switch (sq->type) {
case PIPE_QUERY_OCCLUSION_COUNTER:
sq->start = softpipe->occlusion_count;
@@ -83,6 +88,13 @@ softpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
case PIPE_QUERY_TIME_ELAPSED:
sq->start = 1000*os_time_get();
break;
+ case PIPE_QUERY_SO_STATISTICS:
+ sq->so.num_primitives_written = 0;
+ sq->so.primitives_storage_needed = 0;
+ break;
+ case PIPE_QUERY_GPU_FINISHED:
+ break;
+ case PIPE_QUERY_TIMESTAMP_DISJOINT:
default:
assert(0);
break;
@@ -106,6 +118,15 @@ softpipe_end_query(struct pipe_context *pipe, struct pipe_query *q)
case PIPE_QUERY_TIME_ELAPSED:
sq->end = 1000*os_time_get();
break;
+ case PIPE_QUERY_SO_STATISTICS:
+ sq->so.num_primitives_written =
+ softpipe->so_stats.num_primitives_written;
+ sq->so.primitives_storage_needed =
+ softpipe->so_stats.primitives_storage_needed;
+ break;
+ case PIPE_QUERY_GPU_FINISHED:
+ case PIPE_QUERY_TIMESTAMP_DISJOINT:
+ break;
default:
assert(0);
break;
@@ -118,10 +139,32 @@ static boolean
softpipe_get_query_result(struct pipe_context *pipe,
struct pipe_query *q,
boolean wait,
- uint64_t *result )
+ void *vresult)
{
struct softpipe_query *sq = softpipe_query(q);
- *result = sq->end - sq->start;
+ uint64_t *result = (uint64_t*)vresult;
+
+ switch (sq->type) {
+ case PIPE_QUERY_SO_STATISTICS:
+ memcpy(vresult, &sq->so,
+ sizeof(struct pipe_query_data_so_statistics));
+ break;
+ case PIPE_QUERY_GPU_FINISHED:
+ *result = TRUE;
+ break;
+ case PIPE_QUERY_TIMESTAMP_DISJOINT: {
+ struct pipe_query_data_timestamp_disjoint td;
+ /*os_get_time is in microseconds*/
+ td.frequency = 1000000;
+ td.disjoint = FALSE;
+ memcpy(vresult, &sq->so,
+ sizeof(struct pipe_query_data_timestamp_disjoint));
+ }
+ break;
+ default:
+ *result = sq->end - sq->start;
+ break;
+ }
return TRUE;
}
diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c
index 8abe7f50e1..fc57d3eb61 100644
--- a/src/gallium/drivers/softpipe/sp_screen.c
+++ b/src/gallium/drivers/softpipe/sp_screen.c
@@ -115,6 +115,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
return 1;
+ case PIPE_CAP_STREAM_OUTPUT:
+ return 1;
case PIPE_CAP_MAX_VS_INSTRUCTIONS:
case PIPE_CAP_MAX_FS_INSTRUCTIONS:
diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h
index 5b0faabeae..7d6b86dce0 100644
--- a/src/gallium/drivers/softpipe/sp_state.h
+++ b/src/gallium/drivers/softpipe/sp_state.h
@@ -51,6 +51,8 @@
#define SP_NEW_VS 0x2000
#define SP_NEW_QUERY 0x4000
#define SP_NEW_GS 0x8000
+#define SP_NEW_SO 0x10000
+#define SP_NEW_SO_BUFFERS 0x20000
struct tgsi_sampler;
@@ -98,6 +100,7 @@ struct sp_vertex_shader {
struct sp_geometry_shader {
struct pipe_shader_state shader;
struct draw_geometry_shader *draw_data;
+ int max_sampler;
};
struct sp_velems_state {
@@ -105,6 +108,10 @@ struct sp_velems_state {
struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS];
};
+struct sp_so_state {
+ struct pipe_stream_output_state base;
+};
+
void *
softpipe_create_blend_state(struct pipe_context *,
@@ -122,6 +129,10 @@ void
softpipe_bind_vertex_sampler_states(struct pipe_context *,
unsigned num_samplers,
void **samplers);
+void
+softpipe_bind_geometry_sampler_states(struct pipe_context *,
+ unsigned num_samplers,
+ void **samplers);
void softpipe_delete_sampler_state(struct pipe_context *, void *);
void *
@@ -189,6 +200,11 @@ softpipe_set_vertex_sampler_views(struct pipe_context *,
unsigned num,
struct pipe_sampler_view **);
+void
+softpipe_set_geometry_sampler_views(struct pipe_context *,
+ unsigned num,
+ struct pipe_sampler_view **);
+
struct pipe_sampler_view *
softpipe_create_sampler_view(struct pipe_context *pipe,
struct pipe_resource *texture,
@@ -244,6 +260,8 @@ softpipe_draw_elements_instanced(struct pipe_context *pipe,
unsigned startInstance,
unsigned instanceCount);
+void softpipe_draw_stream_output(struct pipe_context *pipe, unsigned mode);
+
void
softpipe_map_transfers(struct softpipe_context *sp);
@@ -263,5 +281,20 @@ softpipe_get_vertex_info(struct softpipe_context *softpipe);
struct vertex_info *
softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe);
+void *
+softpipe_create_stream_output_state(
+ struct pipe_context *pipe,
+ const struct pipe_stream_output_state *templ);
+void
+softpipe_bind_stream_output_state(struct pipe_context *pipe,
+ void *so);
+void
+softpipe_delete_stream_output_state(struct pipe_context *pipe, void *so);
+
+void
+softpipe_set_stream_output_buffers(struct pipe_context *pipe,
+ struct pipe_resource **buffers,
+ int *offsets,
+ int num_buffers);
#endif
diff --git a/src/gallium/drivers/softpipe/sp_state_derived.c b/src/gallium/drivers/softpipe/sp_state_derived.c
index 4c6d4909f5..3ba4d934fd 100644
--- a/src/gallium/drivers/softpipe/sp_state_derived.c
+++ b/src/gallium/drivers/softpipe/sp_state_derived.c
@@ -225,6 +225,19 @@ update_tgsi_samplers( struct softpipe_context *softpipe )
}
}
}
+
+ for (i = 0; i < PIPE_MAX_GEOMETRY_SAMPLERS; i++) {
+ struct softpipe_tex_tile_cache *tc = softpipe->geometry_tex_cache[i];
+
+ if (tc->texture) {
+ struct softpipe_resource *spt = softpipe_resource(tc->texture);
+
+ if (spt->timestamp != tc->timestamp) {
+ sp_tex_tile_cache_validate_texture(tc);
+ tc->timestamp = spt->timestamp;
+ }
+ }
+ }
}
diff --git a/src/gallium/drivers/softpipe/sp_state_fs.c b/src/gallium/drivers/softpipe/sp_state_fs.c
index 2fff80c438..3fbf1f2578 100644
--- a/src/gallium/drivers/softpipe/sp_state_fs.c
+++ b/src/gallium/drivers/softpipe/sp_state_fs.c
@@ -35,6 +35,7 @@
#include "util/u_inlines.h"
#include "draw/draw_context.h"
#include "draw/draw_vs.h"
+#include "draw/draw_gs.h"
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_exec.h"
#include "tgsi/tgsi_scan.h"
@@ -223,6 +224,8 @@ softpipe_create_gs_state(struct pipe_context *pipe,
if (state->draw_data == NULL)
goto fail;
+ state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER];
+
return state;
fail:
diff --git a/src/gallium/drivers/softpipe/sp_state_sampler.c b/src/gallium/drivers/softpipe/sp_state_sampler.c
index 2692f06c92..79d9516ad9 100644
--- a/src/gallium/drivers/softpipe/sp_state_sampler.c
+++ b/src/gallium/drivers/softpipe/sp_state_sampler.c
@@ -121,6 +121,33 @@ softpipe_bind_vertex_sampler_states(struct pipe_context *pipe,
softpipe->dirty |= SP_NEW_SAMPLER;
}
+void
+softpipe_bind_geometry_sampler_states(struct pipe_context *pipe,
+ unsigned num_samplers,
+ void **samplers)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+ unsigned i;
+
+ assert(num_samplers <= PIPE_MAX_GEOMETRY_SAMPLERS);
+
+ /* Check for no-op */
+ if (num_samplers == softpipe->num_geometry_samplers &&
+ !memcmp(softpipe->geometry_samplers, samplers, num_samplers * sizeof(void *)))
+ return;
+
+ draw_flush(softpipe->draw);
+
+ for (i = 0; i < num_samplers; ++i)
+ softpipe->geometry_samplers[i] = samplers[i];
+ for (i = num_samplers; i < PIPE_MAX_GEOMETRY_SAMPLERS; ++i)
+ softpipe->geometry_samplers[i] = NULL;
+
+ softpipe->num_geometry_samplers = num_samplers;
+
+ softpipe->dirty |= SP_NEW_SAMPLER;
+}
+
struct pipe_sampler_view *
softpipe_create_sampler_view(struct pipe_context *pipe,
@@ -210,6 +237,36 @@ softpipe_set_vertex_sampler_views(struct pipe_context *pipe,
softpipe->dirty |= SP_NEW_TEXTURE;
}
+void
+softpipe_set_geometry_sampler_views(struct pipe_context *pipe,
+ unsigned num,
+ struct pipe_sampler_view **views)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+ uint i;
+
+ assert(num <= PIPE_MAX_GEOMETRY_SAMPLERS);
+
+ /* Check for no-op */
+ if (num == softpipe->num_geometry_sampler_views &&
+ !memcmp(softpipe->geometry_sampler_views, views, num * sizeof(struct pipe_sampler_view *))) {
+ return;
+ }
+
+ draw_flush(softpipe->draw);
+
+ for (i = 0; i < PIPE_MAX_GEOMETRY_SAMPLERS; i++) {
+ struct pipe_sampler_view *view = i < num ? views[i] : NULL;
+
+ pipe_sampler_view_reference(&softpipe->geometry_sampler_views[i], view);
+ sp_tex_tile_cache_set_sampler_view(softpipe->geometry_tex_cache[i], view);
+ }
+
+ softpipe->num_geometry_sampler_views = num;
+
+ softpipe->dirty |= SP_NEW_TEXTURE;
+}
+
/**
* Find/create an sp_sampler_varient object for sampling the given texture,
@@ -293,6 +350,30 @@ softpipe_reset_sampler_varients(struct softpipe_context *softpipe)
}
}
+ if (softpipe->gs) {
+ for (i = 0; i <= softpipe->gs->max_sampler; i++) {
+ if (softpipe->geometry_samplers[i]) {
+ struct pipe_resource *texture = NULL;
+
+ if (softpipe->geometry_sampler_views[i]) {
+ texture = softpipe->geometry_sampler_views[i]->texture;
+ }
+
+ softpipe->tgsi.geom_samplers_list[i] =
+ get_sampler_varient(
+ i,
+ sp_sampler(softpipe->geometry_samplers[i]),
+ texture,
+ TGSI_PROCESSOR_GEOMETRY );
+
+ sp_sampler_varient_bind_texture(
+ softpipe->tgsi.geom_samplers_list[i],
+ softpipe->geometry_tex_cache[i],
+ texture );
+ }
+ }
+ }
+
for (i = 0; i <= softpipe->fs->info.file_max[TGSI_FILE_SAMPLER]; i++) {
if (softpipe->sampler[i]) {
struct pipe_resource *texture = NULL;
diff --git a/src/gallium/drivers/softpipe/sp_state_so.c b/src/gallium/drivers/softpipe/sp_state_so.c
new file mode 100644
index 0000000000..cfe23f9e84
--- /dev/null
+++ b/src/gallium/drivers/softpipe/sp_state_so.c
@@ -0,0 +1,124 @@
+/**************************************************************************
+ *
+ * Copyright 2010 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL 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 "sp_context.h"
+#include "sp_state.h"
+#include "sp_texture.h"
+
+#include "util/u_format.h"
+#include "util/u_memory.h"
+#include "draw/draw_context.h"
+
+
+void *
+softpipe_create_stream_output_state(struct pipe_context *pipe,
+ const struct pipe_stream_output_state *templ)
+{
+ struct sp_so_state *so;
+ so = (struct sp_so_state *) CALLOC_STRUCT(sp_so_state);
+
+ if (so) {
+ so->base.num_outputs = templ->num_outputs;
+ so->base.stride = templ->stride;
+ memcpy(so->base.output_buffer,
+ templ->output_buffer,
+ sizeof(int) * templ->num_outputs);
+ memcpy(so->base.register_index,
+ templ->register_index,
+ sizeof(int) * templ->num_outputs);
+ memcpy(so->base.register_mask,
+ templ->register_mask,
+ sizeof(ubyte) * templ->num_outputs);
+ }
+ return so;
+}
+
+void
+softpipe_bind_stream_output_state(struct pipe_context *pipe,
+ void *so)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+ struct sp_so_state *sp_so = (struct sp_so_state *) so;
+
+ softpipe->so = sp_so;
+
+ softpipe->dirty |= SP_NEW_SO;
+
+ if (sp_so)
+ draw_set_so_state(softpipe->draw, &sp_so->base);
+}
+
+void
+softpipe_delete_stream_output_state(struct pipe_context *pipe, void *so)
+{
+ FREE( so );
+}
+
+void
+softpipe_set_stream_output_buffers(struct pipe_context *pipe,
+ struct pipe_resource **buffers,
+ int *offsets,
+ int num_buffers)
+{
+ struct softpipe_context *softpipe = softpipe_context(pipe);
+ int i;
+ void *map_buffers[PIPE_MAX_SO_BUFFERS];
+
+ assert(num_buffers <= PIPE_MAX_SO_BUFFERS);
+ if (num_buffers > PIPE_MAX_SO_BUFFERS)
+ num_buffers = PIPE_MAX_SO_BUFFERS;
+
+ softpipe->dirty |= SP_NEW_SO_BUFFERS;
+
+ for (i = 0; i < num_buffers; ++i) {
+ void *mapped;
+ struct softpipe_resource *res = softpipe_resource(buffers[i]);
+
+ if (!res) {
+ /* the whole call is invalid, bail out */
+ softpipe->so_target.num_buffers = 0;
+ draw_set_mapped_so_buffers(softpipe->draw, 0, 0);
+ return;
+ }
+
+ softpipe->so_target.buffer[i] = res;
+ softpipe->so_target.offset[i] = offsets[i];
+ softpipe->so_target.so_count[i] = 0;
+
+ mapped = res->data;
+ if (offsets[i] >= 0)
+ map_buffers[i] = ((char*)mapped) + offsets[i];
+ else {
+ /* this is a buffer append */
+ assert(!"appending not implemented");
+ map_buffers[i] = mapped;
+ }
+ }
+ softpipe->so_target.num_buffers = num_buffers;
+
+ draw_set_mapped_so_buffers(softpipe->draw, map_buffers, num_buffers);
+}
diff --git a/src/gallium/drivers/softpipe/sp_surface.c b/src/gallium/drivers/softpipe/sp_surface.c
index 99433f7d1d..55b27e6010 100644
--- a/src/gallium/drivers/softpipe/sp_surface.c
+++ b/src/gallium/drivers/softpipe/sp_surface.c
@@ -33,4 +33,6 @@ void
sp_init_surface_functions(struct softpipe_context *sp)
{
sp->pipe.resource_copy_region = util_resource_copy_region;
+ sp->pipe.clear_render_target = util_clear_render_target;
+ sp->pipe.clear_depth_stencil = util_clear_depth_stencil;
}
diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c
index ff83c66d8b..cf7ab81405 100644
--- a/src/gallium/drivers/softpipe/sp_tex_sample.c
+++ b/src/gallium/drivers/softpipe/sp_tex_sample.c
@@ -71,7 +71,7 @@ lerp(float a, float v0, float v1)
/**
- * Do 2D/biliner interpolation of float values.
+ * Do 2D/bilinear interpolation of float values.
* v00, v10, v01 and v11 are typically four texture samples in a square/box.
* a and b are the horizontal and vertical interpolants.
* It's important that this function is inlined when compiled with
diff --git a/src/gallium/drivers/svga/svga_pipe_query.c b/src/gallium/drivers/svga/svga_pipe_query.c
index 96fb4b8e53..579f8034c7 100644
--- a/src/gallium/drivers/svga/svga_pipe_query.c
+++ b/src/gallium/drivers/svga/svga_pipe_query.c
@@ -63,7 +63,7 @@ svga_query( struct pipe_query *q )
static boolean svga_get_query_result(struct pipe_context *pipe,
struct pipe_query *q,
boolean wait,
- uint64_t *result);
+ void *result);
static struct pipe_query *svga_create_query( struct pipe_context *pipe,
unsigned query_type )
@@ -207,13 +207,14 @@ static void svga_end_query(struct pipe_context *pipe,
static boolean svga_get_query_result(struct pipe_context *pipe,
struct pipe_query *q,
boolean wait,
- uint64_t *result)
+ void *vresult)
{
struct svga_context *svga = svga_context( pipe );
struct svga_screen *svgascreen = svga_screen( pipe->screen );
struct svga_winsys_screen *sws = svgascreen->sws;
struct svga_query *sq = svga_query( q );
SVGA3dQueryState state;
+ uint64_t *result = (uint64_t*)vresult;
SVGA_DBG(DEBUG_QUERY, "%s wait: %d\n", __FUNCTION__);
diff --git a/src/gallium/drivers/sw/sw.c b/src/gallium/drivers/sw/sw.c
index 9f156df45f..6b873ecc1b 100644
--- a/src/gallium/drivers/sw/sw.c
+++ b/src/gallium/drivers/sw/sw.c
@@ -2,7 +2,6 @@
#include "util/u_debug.h"
#include "target-helpers/wrap_screen.h"
#include "sw_public.h"
-#include "state_tracker/sw_winsys.h"
/* Helper function to choose and instantiate one of the software rasterizers:
diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c
index 9ca916fe7b..55dd6cf883 100644
--- a/src/gallium/drivers/trace/tr_context.c
+++ b/src/gallium/drivers/trace/tr_context.c
@@ -248,7 +248,7 @@ static INLINE boolean
trace_context_get_query_result(struct pipe_context *_pipe,
struct pipe_query *query,
boolean wait,
- uint64_t *presult)
+ void *presult)
{
struct trace_context *tr_ctx = trace_context(_pipe);
struct pipe_context *pipe = tr_ctx->pipe;
@@ -260,7 +260,7 @@ trace_context_get_query_result(struct pipe_context *_pipe,
trace_dump_arg(ptr, pipe);
_result = pipe->get_query_result(pipe, query, wait, presult);
- result = *presult;
+ result = *((uint64_t*)presult);
trace_dump_arg(uint, result);
trace_dump_ret(bool, _result);