Mesa (gallium-0.2): g3dvl: Allocate one set of bufs, let winsys rename them as necessary.

Younes Manton ymanton at kemper.freedesktop.org
Sat Jan 10 19:12:20 UTC 2009


Module: Mesa
Branch: gallium-0.2
Commit: 87e39466dc49e033c4075f99343856637611b438
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=87e39466dc49e033c4075f99343856637611b438

Author: Younes Manton <younes.m at gmail.com>
Date:   Thu Dec 11 18:05:59 2008 -0500

g3dvl: Allocate one set of bufs, let winsys rename them as necessary.

---

 .../state_trackers/g3dvl/vl_r16snorm_mc_buf.c      |  272 ++++++++++----------
 .../winsys/g3dvl/nouveau/nouveau_winsys_pipe.c     |   64 ++++--
 2 files changed, 178 insertions(+), 158 deletions(-)

diff --git a/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c
index 1583673..337680a 100644
--- a/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c
+++ b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c
@@ -17,16 +17,7 @@
 #include "vl_types.h"
 #include "vl_defs.h"
 
-/*
- * TODO: Dynamically determine number of buf sets to use, based on
- * video size and available mem, since we can easily run out of memory
- * for high res videos.
- * Note: Destroying previous frame's buffers and creating new ones
- * doesn't work, since the buffer are not actually destroyed until their
- * fence is signalled, and if we render fast enough we will create faster
- * than we destroy.
- */
-#define NUM_BUF_SETS 4	/* Number of rotating buffer sets to use */
+const unsigned int DEFAULT_BUF_ALIGNMENT = 256;
 
 enum vlMacroBlockTypeEx
 {
@@ -56,32 +47,67 @@ struct vlR16SnormBufferedMC
 {
 	struct vlRender				base;
 
-	unsigned int				picture_width, picture_height;
+	unsigned int				picture_width;
+	unsigned int				picture_height;
 	enum vlFormat				picture_format;
+	unsigned int				macroblocks_per_picture;
 
-	unsigned int				cur_buf;
 	struct vlSurface			*buffered_surface;
-	struct vlSurface			*past_surface, *future_surface;
+	struct vlSurface			*past_surface;
+	struct vlSurface			*future_surface;
 	struct vlVertex2f			surface_tex_inv_size;
 	struct vlVertex2f			zero_block[3];
 	unsigned int				num_macroblocks;
 	struct vlMpeg2MacroBlock		*macroblocks;
+	struct pipe_surface			*tex_surface[3];
+	short					*texels[3];
 
 	struct pipe_context			*pipe;
 	struct pipe_viewport_state		viewport;
 	struct pipe_framebuffer_state		render_target;
-	struct pipe_sampler_state		*samplers[5];
-	struct pipe_texture			*textures[NUM_BUF_SETS][5];
-	struct pipe_surface			*tex_surface[3];
-	short					*texels[3];
+
+	union
+	{
+		void					*all[5];
+		struct
+		{
+			void				*y;
+			void				*cb;
+			void				*cr;
+			void				*ref[2];
+		};
+	} samplers;
+
+	union
+	{
+		struct pipe_texture			*all[5];
+		struct
+		{
+			struct pipe_texture		*y;
+			struct pipe_texture		*cb;
+			struct pipe_texture		*cr;
+			struct pipe_texture		*ref[2];
+		};
+	} textures;
+
+	union
+	{
+		struct pipe_vertex_buffer 		all[3];
+		struct
+		{
+			struct pipe_vertex_buffer	ycbcr;
+			struct pipe_vertex_buffer	ref[2];
+		};
+	} vertex_bufs;
+
 	void					*i_vs, *p_vs[2], *b_vs[2];
 	void					*i_fs, *p_fs[2], *b_fs[2];
-	struct pipe_vertex_buffer 		vertex_bufs[NUM_BUF_SETS][3];
 	struct pipe_vertex_element		vertex_elems[8];
-	struct pipe_constant_buffer		vs_const_buf, fs_const_buf;
+	struct pipe_constant_buffer		vs_const_buf;
+	struct pipe_constant_buffer		fs_const_buf;
 };
 
-static int vlBegin
+static inline int vlBegin
 (
 	struct vlRender *render
 )
@@ -382,7 +408,7 @@ static inline int vlGrabMacroBlockVB
 			vb = (struct vlVertex2f*)mc->pipe->winsys->buffer_map
 			(
 				mc->pipe->winsys,
-				mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS][2].buffer,
+				mc->vertex_bufs.ref[1].buffer,
 				PIPE_BUFFER_USAGE_CPU_WRITE
 			) + pos * 2 * 24;
 
@@ -411,7 +437,7 @@ static inline int vlGrabMacroBlockVB
 				}
 			}
 
-			mc->pipe->winsys->buffer_unmap(mc->pipe->winsys, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS][2].buffer);
+			mc->pipe->winsys->buffer_unmap(mc->pipe->winsys, mc->vertex_bufs.ref[1].buffer);
 
 			/* fall-through */
 		}
@@ -423,7 +449,7 @@ static inline int vlGrabMacroBlockVB
 			vb = (struct vlVertex2f*)mc->pipe->winsys->buffer_map
 			(
 				mc->pipe->winsys,
-				mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS][1].buffer,
+				mc->vertex_bufs.ref[0].buffer,
 				PIPE_BUFFER_USAGE_CPU_WRITE
 			) + pos * 2 * 24;
 
@@ -469,7 +495,7 @@ static inline int vlGrabMacroBlockVB
 				}
 			}
 
-			mc->pipe->winsys->buffer_unmap(mc->pipe->winsys, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS][1].buffer);
+			mc->pipe->winsys->buffer_unmap(mc->pipe->winsys, mc->vertex_bufs.ref[0].buffer);
 
 			/* fall-through */
 		}
@@ -497,7 +523,7 @@ static inline int vlGrabMacroBlockVB
 			vb = (struct vlMacroBlockVertexStream0*)mc->pipe->winsys->buffer_map
 			(
 				mc->pipe->winsys,
-				mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS][0].buffer,
+				mc->vertex_bufs.ycbcr.buffer,
 				PIPE_BUFFER_USAGE_CPU_WRITE
 			) + pos * 24;
 
@@ -533,7 +559,7 @@ static inline int vlGrabMacroBlockVB
 				4, 2, 1, mc->zero_block
 			);
 
-			mc->pipe->winsys->buffer_unmap(mc->pipe->winsys, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS][0].buffer);
+			mc->pipe->winsys->buffer_unmap(mc->pipe->winsys, mc->vertex_bufs.ycbcr.buffer);
 
 			break;
 		}
@@ -555,9 +581,6 @@ static int vlFlush
 	unsigned int			num_macroblocks[vlNumMacroBlockExTypes] = {0};
 	unsigned int			offset[vlNumMacroBlockExTypes];
 	unsigned int			vb_start = 0;
-	unsigned int			mbw;
-	unsigned int			mbh;
-	unsigned int			num_mb_per_frame;
 	unsigned int			i;
 
 	assert(render);
@@ -567,11 +590,7 @@ static int vlFlush
 	if (!mc->buffered_surface)
 		return 0;
 
-	mbw = align(mc->picture_width, VL_MACROBLOCK_WIDTH) / VL_MACROBLOCK_WIDTH;
-	mbh = align(mc->picture_height, VL_MACROBLOCK_HEIGHT) / VL_MACROBLOCK_HEIGHT;
-	num_mb_per_frame = mbw * mbh;
-
-	if (mc->num_macroblocks < num_mb_per_frame)
+	if (mc->num_macroblocks < mc->macroblocks_per_picture)
 		return 0;
 
 	pipe = mc->pipe;
@@ -628,10 +647,10 @@ static int vlFlush
 
 	if (num_macroblocks[vlMacroBlockExTypeIntra] > 0)
 	{
-		pipe->set_vertex_buffers(pipe, 1, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS]);
+		pipe->set_vertex_buffers(pipe, 1, mc->vertex_bufs.all);
 		pipe->set_vertex_elements(pipe, 4, mc->vertex_elems);
-		pipe->set_sampler_textures(pipe, 3, mc->textures[mc->cur_buf % NUM_BUF_SETS]);
-		pipe->bind_sampler_states(pipe, 3, (void**)mc->samplers);
+		pipe->set_sampler_textures(pipe, 3, mc->textures.all);
+		pipe->bind_sampler_states(pipe, 3, mc->samplers.all);
 		pipe->bind_vs_state(pipe, mc->i_vs);
 		pipe->bind_fs_state(pipe, mc->i_fs);
 
@@ -641,11 +660,11 @@ static int vlFlush
 
 	if (num_macroblocks[vlMacroBlockExTypeFwdPredictedFrame] > 0)
 	{
-		pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS]);
+		pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs.all);
 		pipe->set_vertex_elements(pipe, 6, mc->vertex_elems);
-		mc->textures[mc->cur_buf % NUM_BUF_SETS][3] = mc->past_surface->texture;
-		pipe->set_sampler_textures(pipe, 4, mc->textures[mc->cur_buf % NUM_BUF_SETS]);
-		pipe->bind_sampler_states(pipe, 4, (void**)mc->samplers);
+		mc->textures.ref[0] = mc->past_surface->texture;
+		pipe->set_sampler_textures(pipe, 4, mc->textures.all);
+		pipe->bind_sampler_states(pipe, 4, mc->samplers.all);
 		pipe->bind_vs_state(pipe, mc->p_vs[0]);
 		pipe->bind_fs_state(pipe, mc->p_fs[0]);
 
@@ -655,11 +674,11 @@ static int vlFlush
 
 	if (num_macroblocks[vlMacroBlockExTypeFwdPredictedField] > 0)
 	{
-		pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS]);
+		pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs.all);
 		pipe->set_vertex_elements(pipe, 6, mc->vertex_elems);
-		mc->textures[mc->cur_buf % NUM_BUF_SETS][3] = mc->past_surface->texture;
-		pipe->set_sampler_textures(pipe, 4, mc->textures[mc->cur_buf % NUM_BUF_SETS]);
-		pipe->bind_sampler_states(pipe, 4, (void**)mc->samplers);
+		mc->textures.ref[0] = mc->past_surface->texture;
+		pipe->set_sampler_textures(pipe, 4, mc->textures.all);
+		pipe->bind_sampler_states(pipe, 4, mc->samplers.all);
 		pipe->bind_vs_state(pipe, mc->p_vs[1]);
 		pipe->bind_fs_state(pipe, mc->p_fs[1]);
 
@@ -669,11 +688,11 @@ static int vlFlush
 
 	if (num_macroblocks[vlMacroBlockExTypeBkwdPredictedFrame] > 0)
 	{
-		pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS]);
+		pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs.all);
 		pipe->set_vertex_elements(pipe, 6, mc->vertex_elems);
-		mc->textures[mc->cur_buf % NUM_BUF_SETS][3] = mc->future_surface->texture;
-		pipe->set_sampler_textures(pipe, 4, mc->textures[mc->cur_buf % NUM_BUF_SETS]);
-		pipe->bind_sampler_states(pipe, 4, (void**)mc->samplers);
+		mc->textures.ref[0] = mc->future_surface->texture;
+		pipe->set_sampler_textures(pipe, 4, mc->textures.all);
+		pipe->bind_sampler_states(pipe, 4, mc->samplers.all);
 		pipe->bind_vs_state(pipe, mc->p_vs[0]);
 		pipe->bind_fs_state(pipe, mc->p_fs[0]);
 
@@ -683,11 +702,11 @@ static int vlFlush
 
 	if (num_macroblocks[vlMacroBlockExTypeBkwdPredictedField] > 0)
 	{
-		pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS]);
+		pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs.all);
 		pipe->set_vertex_elements(pipe, 6, mc->vertex_elems);
-		mc->textures[mc->cur_buf % NUM_BUF_SETS][3] = mc->future_surface->texture;
-		pipe->set_sampler_textures(pipe, 4, mc->textures[mc->cur_buf % NUM_BUF_SETS]);
-		pipe->bind_sampler_states(pipe, 4, (void**)mc->samplers);
+		mc->textures.ref[0] = mc->future_surface->texture;
+		pipe->set_sampler_textures(pipe, 4, mc->textures.all);
+		pipe->bind_sampler_states(pipe, 4, mc->samplers.all);
 		pipe->bind_vs_state(pipe, mc->p_vs[1]);
 		pipe->bind_fs_state(pipe, mc->p_fs[1]);
 
@@ -697,12 +716,12 @@ static int vlFlush
 
 	if (num_macroblocks[vlMacroBlockExTypeBiPredictedFrame] > 0)
 	{
-		pipe->set_vertex_buffers(pipe, 3, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS]);
+		pipe->set_vertex_buffers(pipe, 3, mc->vertex_bufs.all);
 		pipe->set_vertex_elements(pipe, 8, mc->vertex_elems);
-		mc->textures[mc->cur_buf % NUM_BUF_SETS][3] = mc->past_surface->texture;
-		mc->textures[mc->cur_buf % NUM_BUF_SETS][4] = mc->future_surface->texture;
-		pipe->set_sampler_textures(pipe, 5, mc->textures[mc->cur_buf % NUM_BUF_SETS]);
-		pipe->bind_sampler_states(pipe, 5, (void**)mc->samplers);
+		mc->textures.ref[0] = mc->past_surface->texture;
+		mc->textures.ref[1] = mc->future_surface->texture;
+		pipe->set_sampler_textures(pipe, 5, mc->textures.all);
+		pipe->bind_sampler_states(pipe, 5, mc->samplers.all);
 		pipe->bind_vs_state(pipe, mc->b_vs[0]);
 		pipe->bind_fs_state(pipe, mc->b_fs[0]);
 
@@ -712,12 +731,12 @@ static int vlFlush
 
 	if (num_macroblocks[vlMacroBlockExTypeBiPredictedField] > 0)
 	{
-		pipe->set_vertex_buffers(pipe, 3, mc->vertex_bufs[mc->cur_buf % NUM_BUF_SETS]);
+		pipe->set_vertex_buffers(pipe, 3, mc->vertex_bufs.all);
 		pipe->set_vertex_elements(pipe, 8, mc->vertex_elems);
-		mc->textures[mc->cur_buf % NUM_BUF_SETS][3] = mc->past_surface->texture;
-		mc->textures[mc->cur_buf % NUM_BUF_SETS][4] = mc->future_surface->texture;
-		pipe->set_sampler_textures(pipe, 5, mc->textures[mc->cur_buf % NUM_BUF_SETS]);
-		pipe->bind_sampler_states(pipe, 5, (void**)mc->samplers);
+		mc->textures.ref[0] = mc->past_surface->texture;
+		mc->textures.ref[1] = mc->future_surface->texture;
+		pipe->set_sampler_textures(pipe, 5, mc->textures.all);
+		pipe->bind_sampler_states(pipe, 5, mc->samplers.all);
 		pipe->bind_vs_state(pipe, mc->b_vs[1]);
 		pipe->bind_fs_state(pipe, mc->b_fs[1]);
 
@@ -732,7 +751,6 @@ static int vlFlush
 
 	mc->buffered_surface = NULL;
 	mc->num_macroblocks = 0;
-	mc->cur_buf++;
 
 	return 0;
 }
@@ -745,6 +763,7 @@ static int vlRenderMacroBlocksMpeg2R16SnormBuffered
 )
 {
 	struct vlR16SnormBufferedMC	*mc;
+	bool				new_surface = false;
 	unsigned int			i;
 
 	assert(render);
@@ -756,39 +775,26 @@ static int vlRenderMacroBlocksMpeg2R16SnormBuffered
 		if (mc->buffered_surface != surface)
 		{
 			vlFlush(&mc->base);
-			mc->buffered_surface = surface;
-			mc->past_surface = batch->past_surface;
-			mc->future_surface = batch->future_surface;
-			mc->surface_tex_inv_size.x = 1.0f / surface->texture->width[0];
-			mc->surface_tex_inv_size.y = 1.0f / surface->texture->height[0];
-			
-			for (i = 0; i < 3; ++i)
-			{
-				mc->tex_surface[i] = mc->pipe->screen->get_tex_surface
-				(
-					mc->pipe->screen,
-					mc->textures[mc->cur_buf % NUM_BUF_SETS][i],
-					0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE
-				);
-
-				mc->texels[i] = pipe_surface_map(mc->tex_surface[i], PIPE_BUFFER_USAGE_CPU_WRITE);
-			}
+			new_surface = true;
 		}
 	}
 	else
+		new_surface = true;
+
+	if (new_surface)
 	{
 		mc->buffered_surface = surface;
 		mc->past_surface = batch->past_surface;
 		mc->future_surface = batch->future_surface;
 		mc->surface_tex_inv_size.x = 1.0f / surface->texture->width[0];
 		mc->surface_tex_inv_size.y = 1.0f / surface->texture->height[0];
-		
+
 		for (i = 0; i < 3; ++i)
 		{
 			mc->tex_surface[i] = mc->pipe->screen->get_tex_surface
 			(
 				mc->pipe->screen,
-				mc->textures[mc->cur_buf % NUM_BUF_SETS][i],
+				mc->textures.all[i],
 				0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE
 			);
 
@@ -802,7 +808,7 @@ static int vlRenderMacroBlocksMpeg2R16SnormBuffered
 	return 0;
 }
 
-static int vlEnd
+static inline int vlEnd
 (
 	struct vlRender *render
 )
@@ -819,7 +825,7 @@ static int vlDestroy
 {
 	struct vlR16SnormBufferedMC	*mc;
 	struct pipe_context		*pipe;
-	unsigned int			h, i;
+	unsigned int			i;
 
 	assert(render);
 
@@ -827,19 +833,14 @@ static int vlDestroy
 	pipe = mc->pipe;
 
 	for (i = 0; i < 5; ++i)
-		pipe->delete_sampler_state(pipe, mc->samplers[i]);
+		pipe->delete_sampler_state(pipe, mc->samplers.all[i]);
 
-	for (h = 0; h < NUM_BUF_SETS; ++h)
-			for (i = 0; i < 3; ++i)
-				pipe->winsys->buffer_destroy(pipe->winsys, mc->vertex_bufs[h][i].buffer);
+	for (i = 0; i < 3; ++i)
+		pipe->winsys->buffer_destroy(pipe->winsys, mc->vertex_bufs.all[i].buffer);
 
 	/* Textures 3 & 4 are not created directly, no need to release them here */
-	for (i = 0; i < NUM_BUF_SETS; ++i)
-	{
-		pipe_texture_release(&mc->textures[i][0]);
-		pipe_texture_release(&mc->textures[i][1]);
-		pipe_texture_release(&mc->textures[i][2]);
-	}
+	for (i = 0; i < 3; ++i)
+		pipe_texture_release(&mc->textures.all[i]);
 
 	pipe->delete_vs_state(pipe, mc->i_vs);
 	pipe->delete_fs_state(pipe, mc->i_fs);
@@ -882,42 +883,39 @@ static int vlCreateDataBufs
 {
 	const unsigned int	mbw = align(mc->picture_width, VL_MACROBLOCK_WIDTH) / VL_MACROBLOCK_WIDTH;
 	const unsigned int	mbh = align(mc->picture_height, VL_MACROBLOCK_HEIGHT) / VL_MACROBLOCK_HEIGHT;
-	const unsigned int	num_mb_per_frame = mbw * mbh;
 
 	struct pipe_context	*pipe;
-	unsigned int		h, i;
+	unsigned int		i;
 
 	assert(mc);
 
 	pipe = mc->pipe;
+	mc->macroblocks_per_picture = mbw * mbh;
 
 	/* Create our vertex buffers */
-	for (h = 0; h < NUM_BUF_SETS; ++h)
+	mc->vertex_bufs.ycbcr.pitch = sizeof(struct vlVertex2f) * 4;
+	mc->vertex_bufs.ycbcr.max_index = 24 * mc->macroblocks_per_picture - 1;
+	mc->vertex_bufs.ycbcr.buffer_offset = 0;
+	mc->vertex_bufs.ycbcr.buffer = pipe->winsys->buffer_create
+	(
+		pipe->winsys,
+		DEFAULT_BUF_ALIGNMENT,
+		PIPE_BUFFER_USAGE_VERTEX,
+		sizeof(struct vlVertex2f) * 4 * 24 * mc->macroblocks_per_picture
+	);
+
+	for (i = 1; i < 3; ++i)
 	{
-		mc->vertex_bufs[h][0].pitch = sizeof(struct vlVertex2f) * 4;
-		mc->vertex_bufs[h][0].max_index = 24 * num_mb_per_frame - 1;
-		mc->vertex_bufs[h][0].buffer_offset = 0;
-		mc->vertex_bufs[h][0].buffer = pipe->winsys->buffer_create
+		mc->vertex_bufs.all[i].pitch = sizeof(struct vlVertex2f) * 2;
+		mc->vertex_bufs.all[i].max_index = 24 * mc->macroblocks_per_picture - 1;
+		mc->vertex_bufs.all[i].buffer_offset = 0;
+		mc->vertex_bufs.all[i].buffer = pipe->winsys->buffer_create
 		(
 			pipe->winsys,
-			1,
+			DEFAULT_BUF_ALIGNMENT,
 			PIPE_BUFFER_USAGE_VERTEX,
-			sizeof(struct vlVertex2f) * 4 * 24 * num_mb_per_frame
+			sizeof(struct vlVertex2f) * 2 * 24 * mc->macroblocks_per_picture
 		);
-
-		for (i = 1; i < 3; ++i)
-		{
-			mc->vertex_bufs[h][i].pitch = sizeof(struct vlVertex2f) * 2;
-			mc->vertex_bufs[h][i].max_index = 24 * num_mb_per_frame - 1;
-			mc->vertex_bufs[h][i].buffer_offset = 0;
-			mc->vertex_bufs[h][i].buffer = pipe->winsys->buffer_create
-			(
-				pipe->winsys,
-				1,
-				PIPE_BUFFER_USAGE_VERTEX,
-				sizeof(struct vlVertex2f) * 2 * 24 * num_mb_per_frame
-			);
-		}
 	}
 
 	/* Position element */
@@ -973,7 +971,7 @@ static int vlCreateDataBufs
 	mc->vs_const_buf.buffer = pipe->winsys->buffer_create
 	(
 		pipe->winsys,
-		1,
+		DEFAULT_BUF_ALIGNMENT,
 		PIPE_BUFFER_USAGE_CONSTANT,
 		mc->vs_const_buf.size
 	);
@@ -982,7 +980,7 @@ static int vlCreateDataBufs
 	mc->fs_const_buf.buffer = pipe->winsys->buffer_create
 	(
 		pipe->winsys,
-		1,
+		DEFAULT_BUF_ALIGNMENT,
 		PIPE_BUFFER_USAGE_CONSTANT,
 		mc->fs_const_buf.size
 	);
@@ -996,7 +994,7 @@ static int vlCreateDataBufs
 
 	pipe->winsys->buffer_unmap(pipe->winsys, mc->fs_const_buf.buffer);
 
-	mc->macroblocks = malloc(sizeof(struct vlMpeg2MacroBlock) * num_mb_per_frame);
+	mc->macroblocks = malloc(sizeof(struct vlMpeg2MacroBlock) * mc->macroblocks_per_picture);
 
 	return 0;
 }
@@ -1016,6 +1014,13 @@ static int vlInit
 
 	pipe = mc->pipe;
 
+	mc->buffered_surface = NULL;
+	mc->past_surface = NULL;
+	mc->future_surface = NULL;
+	for (i = 0; i < 3; ++i)
+		mc->zero_block[i].x = -1.0f;
+	mc->num_macroblocks = 0;
+
 	/* For MC we render to textures, which are rounded up to nearest POT */
 	mc->viewport.scale[0] = vlRoundUpPOT(mc->picture_width);
 	mc->viewport.scale[1] = vlRoundUpPOT(mc->picture_height);
@@ -1057,7 +1062,7 @@ static int vlInit
 		/*sampler.max_lod = ;*/
 		/*sampler.border_color[i] = ;*/
 		/*sampler.max_anisotropy = ;*/
-		mc->samplers[i] = pipe->create_sampler_state(pipe, &sampler);
+		mc->samplers.all[i] = pipe->create_sampler_state(pipe, &sampler);
 	}
 
 	memset(&template, 0, sizeof(struct pipe_texture));
@@ -1071,8 +1076,7 @@ static int vlInit
 	pf_get_block(template.format, &template.block);
 	template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER | PIPE_TEXTURE_USAGE_DYNAMIC;
 
-	for (i = 0; i < NUM_BUF_SETS; ++i)
-		mc->textures[i][0] = pipe->screen->texture_create(pipe->screen, &template);
+	mc->textures.y = pipe->screen->texture_create(pipe->screen, &template);
 
 	if (mc->picture_format == vlFormatYCbCr420)
 	{
@@ -1082,13 +1086,10 @@ static int vlInit
 	else if (mc->picture_format == vlFormatYCbCr422)
 		template.height[0] = vlRoundUpPOT(mc->picture_height / 2);
 
-	for (i = 0; i < NUM_BUF_SETS; ++i)
-	{
-		mc->textures[i][1] = pipe->screen->texture_create(pipe->screen, &template);
-		mc->textures[i][2] = pipe->screen->texture_create(pipe->screen, &template);
-	}
+	mc->textures.cb = pipe->screen->texture_create(pipe->screen, &template);
+	mc->textures.cr = pipe->screen->texture_create(pipe->screen, &template);
 
-	/* textures[3] & textures[4] are assigned from vlSurfaces for P and B macroblocks at render time */
+	/* textures.all[3] & textures.all[4] are assigned from vlSurfaces for P and B macroblocks at render time */
 
 	vlCreateVertexShaderIMB(mc);
 	vlCreateFragmentShaderIMB(mc);
@@ -1114,8 +1115,7 @@ int vlCreateR16SNormBufferedMC
 	struct vlRender **render
 )
 {
-	struct vlR16SnormBufferedMC	*mc;
-	unsigned int			i;
+	struct vlR16SnormBufferedMC *mc;
 
 	assert(pipe);
 	assert(render);
@@ -1131,14 +1131,6 @@ int vlCreateR16SNormBufferedMC
 	mc->picture_width = picture_width;
 	mc->picture_height = picture_height;
 
-	mc->cur_buf = 0;
-	mc->buffered_surface = NULL;
-	mc->past_surface = NULL;
-	mc->future_surface = NULL;
-	for (i = 0; i < 3; ++i)
-		mc->zero_block[i].x = -1.0f;
-	mc->num_macroblocks = 0;
-
 	vlInit(mc);
 
 	*render = &mc->base;
diff --git a/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_pipe.c b/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_pipe.c
index d841eb4..17c409e 100644
--- a/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_pipe.c
+++ b/src/gallium/winsys/g3dvl/nouveau/nouveau_winsys_pipe.c
@@ -89,25 +89,10 @@ nouveau_surface_release(struct pipe_winsys *ws, struct pipe_surface **s)
 	}
 }
 
-static struct pipe_buffer *
-nouveau_pipe_bo_create(struct pipe_winsys *pws, unsigned alignment,
-		       unsigned usage, unsigned size)
+static uint32_t
+nouveau_flags_from_usage(struct nouveau_context *nv, unsigned usage)
 {
-	struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws;
-	struct nouveau_context *nv = nvpws->nv;
-	struct nouveau_device *dev = nv->nv_screen->device;
-	struct nouveau_pipe_buffer *nvbuf;
-	uint32_t flags;
-
-	nvbuf = calloc(1, sizeof(*nvbuf));
-	if (!nvbuf)
-		return NULL;
-	nvbuf->base.refcount = 1;
-	nvbuf->base.alignment = alignment;
-	nvbuf->base.usage = usage;
-	nvbuf->base.size = size;
-
-	flags = NOUVEAU_BO_LOCAL;
+	uint32_t flags = NOUVEAU_BO_LOCAL;
 
 	if (usage & PIPE_BUFFER_USAGE_PIXEL) {
 		if (usage & NOUVEAU_BUFFER_USAGE_TEXTURE)
@@ -126,6 +111,29 @@ nouveau_pipe_bo_create(struct pipe_winsys *pws, unsigned alignment,
 			flags |= NOUVEAU_BO_GART;
 	}
 
+	return flags;
+}
+
+static struct pipe_buffer *
+nouveau_pipe_bo_create(struct pipe_winsys *pws, unsigned alignment,
+		       unsigned usage, unsigned size)
+{
+	struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws;
+	struct nouveau_context *nv = nvpws->nv;
+	struct nouveau_device *dev = nv->nv_screen->device;
+	struct nouveau_pipe_buffer *nvbuf;
+	uint32_t flags;
+
+	nvbuf = calloc(1, sizeof(*nvbuf));
+	if (!nvbuf)
+		return NULL;
+	nvbuf->base.refcount = 1;
+	nvbuf->base.alignment = alignment;
+	nvbuf->base.usage = usage;
+	nvbuf->base.size = size;
+
+	flags = nouveau_flags_from_usage(nv, usage);
+
 	if (nouveau_bo_new(dev, flags, alignment, size, &nvbuf->bo)) {
 		free(nvbuf);
 		return NULL;
@@ -176,6 +184,26 @@ nouveau_pipe_bo_map(struct pipe_winsys *pws, struct pipe_buffer *buf,
 	if (flags & PIPE_BUFFER_USAGE_CPU_WRITE)
 		map_flags |= NOUVEAU_BO_WR;
 
+	if ((map_flags & NOUVEAU_BO_RDWR) == NOUVEAU_BO_WR &&
+	    !nouveau_bo_busy(nvbuf->bo, map_flags)) {
+		/* XXX: Technically incorrect. If the client maps a buffer for write-only
+		 * and leaves part of the buffer untouched it probably expects those parts
+		 * to remain intact. This is violated because we allocate a whole new buffer
+		 * and don't copy the previous buffer's contents, so this optimization is
+		 * only valid if the client intends to overwrite the whole buffer.
+		 */
+		struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws;
+		struct nouveau_context *nv = nvpws->nv;
+		struct nouveau_device *dev = nv->nv_screen->device;
+		struct nouveau_bo *rename;
+		uint32_t flags = nouveau_flags_from_usage(nv, buf->usage);
+
+		if (!nouveau_bo_new(dev, flags, buf->alignment, buf->size, &rename)) {
+			nouveau_bo_del(&nvbuf->bo);
+			nvbuf->bo = rename;
+		}
+	}
+
 	if (nouveau_bo_map(nvbuf->bo, map_flags))
 		return NULL;
 	return nvbuf->bo->map;




More information about the mesa-commit mailing list