summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <anholt@FreeBSD.org>2006-11-29 01:16:12 +0000
committerEric Anholt <anholt@FreeBSD.org>2006-11-29 01:16:12 +0000
commit3cd06cf8c5ef6a27e36c584e12ba79ed8dacbf28 (patch)
tree01b1c257356478a276827a7b7f670b7caae051a9
parent716091a6a0a9a4cc03f0aa61a3a6518b0648f167 (diff)
Add accelerated CopyPixels for non-overlapping, 1:1 blits.
Submitted by Gary Wong <gtw@gnu.org>
-rw-r--r--src/mesa/drivers/dri/i965/brw_context.c2
-rw-r--r--src/mesa/drivers/dri/i965/brw_context.h6
-rw-r--r--src/mesa/drivers/dri/i965/brw_metaops.c98
-rw-r--r--src/mesa/drivers/dri/i965/brw_tex.c32
-rw-r--r--src/mesa/drivers/dri/i965/brw_vtbl.c1
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_surface_state.c6
-rw-r--r--src/mesa/drivers/dri/i965/intel_buffers.c2
-rw-r--r--src/mesa/drivers/dri/i965/intel_context.h11
-rw-r--r--src/mesa/drivers/dri/i965/intel_pixel_copy.c67
-rw-r--r--src/mesa/drivers/dri/i965/intel_tex_validate.c3
10 files changed, 213 insertions, 15 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
index c1f6617f3f..bc422c1a50 100644
--- a/src/mesa/drivers/dri/i965/brw_context.c
+++ b/src/mesa/drivers/dri/i965/brw_context.c
@@ -156,6 +156,8 @@ GLboolean brwCreateContext( const __GLcontextModes *mesaVis,
brw_ProgramCacheInit( ctx );
+ brw_FrameBufferTexInit( brw );
+
/* Hook our functions into exec and compile dispatch tables. Only
* fallback on out-of-memory situations.
*/
diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
index 1137bfd2c7..a57c794834 100644
--- a/src/mesa/drivers/dri/i965/brw_context.h
+++ b/src/mesa/drivers/dri/i965/brw_context.h
@@ -485,7 +485,7 @@ struct brw_context
*/
struct brw_state_pointers attribs;
struct gl_vertex_program *vp;
- struct gl_fragment_program *fp;
+ struct gl_fragment_program *fp, *fp_tex;
struct gl_buffer_object *vbo;
@@ -493,6 +493,8 @@ struct brw_context
struct intel_region *saved_depth_region;
GLuint restore_draw_mask;
+ struct gl_fragment_program *restore_fp;
+
GLboolean active;
} metaops;
@@ -672,6 +674,8 @@ void brw_destroy_state( struct brw_context *brw );
*/
void brwUpdateTextureState( struct intel_context *intel );
void brwInitTextureFuncs( struct dd_function_table *functions );
+void brw_FrameBufferTexInit( struct brw_context *brw );
+void brw_FrameBufferTexDestroy( struct brw_context *brw );
/*======================================================================
* brw_metaops.c
diff --git a/src/mesa/drivers/dri/i965/brw_metaops.c b/src/mesa/drivers/dri/i965/brw_metaops.c
index 18ca7b1341..ca8e1d3080 100644
--- a/src/mesa/drivers/dri/i965/brw_metaops.c
+++ b/src/mesa/drivers/dri/i965/brw_metaops.c
@@ -27,6 +27,7 @@
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
+ * frame buffer texture by Gary Wong <gtw@gnu.org>
*/
@@ -94,22 +95,26 @@ static void init_attribs( struct brw_context *brw )
DUP(brw, gl_fragment_program_state, FragmentProgram);
}
-static void install_attribs( struct brw_context *brw )
+static void install_vertex_attribs( struct brw_context *brw )
{
- INSTALL(brw, Color, _NEW_COLOR);
- INSTALL(brw, Depth, _NEW_DEPTH);
- INSTALL(brw, Fog, _NEW_FOG);
INSTALL(brw, Hint, _NEW_HINT);
INSTALL(brw, Light, _NEW_LIGHT);
INSTALL(brw, Line, _NEW_LINE);
INSTALL(brw, Point, _NEW_POINT);
INSTALL(brw, Polygon, _NEW_POLYGON);
- INSTALL(brw, Scissor, _NEW_SCISSOR);
- INSTALL(brw, Stencil, _NEW_STENCIL);
- INSTALL(brw, Texture, _NEW_TEXTURE);
INSTALL(brw, Transform, _NEW_TRANSFORM);
INSTALL(brw, Viewport, _NEW_VIEWPORT);
INSTALL(brw, VertexProgram, _NEW_PROGRAM);
+}
+
+static void install_fragment_attribs( struct brw_context *brw )
+{
+ INSTALL(brw, Color, _NEW_COLOR);
+ INSTALL(brw, Depth, _NEW_DEPTH);
+ INSTALL(brw, Fog, _NEW_FOG);
+ INSTALL(brw, Scissor, _NEW_SCISSOR);
+ INSTALL(brw, Stencil, _NEW_STENCIL);
+ INSTALL(brw, Texture, _NEW_TEXTURE);
INSTALL(brw, FragmentProgram, _NEW_PROGRAM);
}
@@ -144,6 +149,15 @@ static const char *fp_prog =
"MOV result.color, fragment.color;\n"
"END\n";
+static const char *fp_tex_prog =
+ "!!ARBfp1.0\n"
+ "TEMP a;\n"
+ "ADD a, fragment.position, program.local[0];\n"
+ "MUL a, a, program.local[1];\n"
+ "TEX result.color, a, texture[0], 2D;\n"
+ "MOV result.depth.z, fragment.position;\n"
+ "END\n";
+
/* Derived values of importance:
*
* FragmentProgram->_Current
@@ -170,6 +184,9 @@ static void init_metaops_state( struct brw_context *brw )
brw->metaops.fp = (struct gl_fragment_program *)
ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 1 );
+ brw->metaops.fp_tex = (struct gl_fragment_program *)
+ ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 1 );
+
brw->metaops.vp = (struct gl_vertex_program *)
ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 1 );
@@ -177,6 +194,10 @@ static void init_metaops_state( struct brw_context *brw )
fp_prog, strlen(fp_prog),
brw->metaops.fp);
+ _mesa_parse_arb_fragment_program(ctx, GL_FRAGMENT_PROGRAM_ARB,
+ fp_tex_prog, strlen(fp_tex_prog),
+ brw->metaops.fp_tex);
+
_mesa_parse_arb_vertex_program(ctx, GL_VERTEX_PROGRAM_ARB,
vp_prog, strlen(vp_prog),
brw->metaops.vp);
@@ -267,7 +288,56 @@ static void meta_color_mask( struct intel_context *intel, GLboolean state )
static void meta_no_texture( struct intel_context *intel )
{
- /* Nothing to do */
+ struct brw_context *brw = brw_context(&intel->ctx);
+
+ brw->metaops.attribs.FragmentProgram->_Current = brw->metaops.fp;
+
+ brw->metaops.attribs.Texture->CurrentUnit = 0;
+ brw->metaops.attribs.Texture->_EnabledUnits = 0;
+ brw->metaops.attribs.Texture->_EnabledCoordUnits = 0;
+ brw->metaops.attribs.Texture->Unit[ 0 ].Enabled = 0;
+ brw->metaops.attribs.Texture->Unit[ 0 ]._ReallyEnabled = 0;
+
+ brw->state.dirty.mesa |= _NEW_TEXTURE | _NEW_PROGRAM;
+}
+
+static void meta_frame_buffer_texture( struct intel_context *intel,
+ GLint xoff, GLint yoff )
+{
+ struct brw_context *brw = brw_context(&intel->ctx);
+ struct intel_region *region = intel_drawbuf_region( intel );
+
+ INSTALL(brw, FragmentProgram, _NEW_PROGRAM);
+
+ brw->metaops.attribs.FragmentProgram->_Current = brw->metaops.fp_tex;
+ /* This is unfortunate, but seems to be necessary, since later on we
+ will end up calling _mesa_load_state_parameters to lookup the
+ local params (below), and that will want to look in ctx.FragmentProgram
+ instead of brw->attribs.FragmentProgram. */
+ intel->ctx.FragmentProgram.Current = brw->metaops.fp_tex;
+
+ brw->metaops.fp_tex->Base.LocalParams[ 0 ][ 0 ] = xoff;
+ brw->metaops.fp_tex->Base.LocalParams[ 0 ][ 1 ] = yoff;
+ brw->metaops.fp_tex->Base.LocalParams[ 0 ][ 2 ] = 0.0;
+ brw->metaops.fp_tex->Base.LocalParams[ 0 ][ 3 ] = 0.0;
+ brw->metaops.fp_tex->Base.LocalParams[ 1 ][ 0 ] =
+ 1.0 / region->pitch;
+ brw->metaops.fp_tex->Base.LocalParams[ 1 ][ 1 ] =
+ -1.0 / region->height;
+ brw->metaops.fp_tex->Base.LocalParams[ 1 ][ 2 ] = 0.0;
+ brw->metaops.fp_tex->Base.LocalParams[ 1 ][ 3 ] = 1.0;
+
+ brw->metaops.attribs.Texture->CurrentUnit = 0;
+ brw->metaops.attribs.Texture->_EnabledUnits = 1;
+ brw->metaops.attribs.Texture->_EnabledCoordUnits = 1;
+ brw->metaops.attribs.Texture->Unit[ 0 ].Enabled = TEXTURE_2D_BIT;
+ brw->metaops.attribs.Texture->Unit[ 0 ]._ReallyEnabled = TEXTURE_2D_BIT;
+ brw->metaops.attribs.Texture->Unit[ 0 ].Current2D =
+ intel->frame_buffer_texobj;
+ brw->metaops.attribs.Texture->Unit[ 0 ]._Current =
+ intel->frame_buffer_texobj;
+
+ brw->state.dirty.mesa |= _NEW_TEXTURE | _NEW_PROGRAM;
}
@@ -406,7 +476,8 @@ static void meta_draw_quad(struct intel_context *intel,
}
-static void install_meta_state( struct intel_context *intel )
+static void install_meta_state( struct intel_context *intel,
+ GLenum state )
{
GLcontext *ctx = &intel->ctx;
struct brw_context *brw = brw_context(ctx);
@@ -415,10 +486,14 @@ static void install_meta_state( struct intel_context *intel )
init_metaops_state(brw);
}
- install_attribs(brw);
+ install_vertex_attribs(brw);
+ if( state == META_FULL )
+ install_fragment_attribs(brw);
+
meta_no_texture(&brw->intel);
meta_flat_shade(&brw->intel);
brw->metaops.restore_draw_mask = ctx->DrawBuffer->_ColorDrawBufferMask[0];
+ brw->metaops.restore_fp = ctx->FragmentProgram.Current;
/* This works without adjusting refcounts. Fix later?
*/
@@ -437,6 +512,7 @@ static void leave_meta_state( struct intel_context *intel )
restore_attribs(brw);
ctx->DrawBuffer->_ColorDrawBufferMask[0] = brw->metaops.restore_draw_mask;
+ ctx->FragmentProgram.Current = brw->metaops.restore_fp;
brw->state.draw_region = brw->metaops.saved_draw_region;
brw->state.depth_region = brw->metaops.saved_depth_region;
@@ -463,6 +539,7 @@ void brw_init_metaops( struct brw_context *brw )
brw->intel.vtbl.meta_depth_replace = meta_depth_replace;
brw->intel.vtbl.meta_color_mask = meta_color_mask;
brw->intel.vtbl.meta_no_texture = meta_no_texture;
+ brw->intel.vtbl.meta_frame_buffer_texture = meta_frame_buffer_texture;
brw->intel.vtbl.meta_draw_region = meta_draw_region;
brw->intel.vtbl.meta_draw_quad = meta_draw_quad;
@@ -479,5 +556,6 @@ void brw_destroy_metaops( struct brw_context *brw )
ctx->Driver.DeleteBuffer( ctx, brw->metaops.vbo );
/* ctx->Driver.DeleteProgram( ctx, brw->metaops.fp ); */
+/* ctx->Driver.DeleteProgram( ctx, brw->metaops.fp_tex ); */
/* ctx->Driver.DeleteProgram( ctx, brw->metaops.vp ); */
}
diff --git a/src/mesa/drivers/dri/i965/brw_tex.c b/src/mesa/drivers/dri/i965/brw_tex.c
index 8332d869e1..c3ffa9e657 100644
--- a/src/mesa/drivers/dri/i965/brw_tex.c
+++ b/src/mesa/drivers/dri/i965/brw_tex.c
@@ -36,11 +36,14 @@
#include "simple_list.h"
#include "enums.h"
#include "image.h"
+#include "teximage.h"
#include "texstore.h"
#include "texformat.h"
#include "texmem.h"
+#include "intel_context.h"
#include "intel_ioctl.h"
+#include "intel_regions.h"
#include "brw_context.h"
#include "brw_defines.h"
@@ -179,3 +182,32 @@ void brwInitTextureFuncs( struct dd_function_table *functions )
{
functions->ChooseTextureFormat = brwChooseTextureFormat;
}
+
+void brw_FrameBufferTexInit( struct brw_context *brw )
+{
+ struct intel_context *intel = &brw->intel;
+ GLcontext *ctx = &intel->ctx;
+ struct intel_region *region = intel->front_region;
+ struct gl_texture_object *obj;
+ struct gl_texture_image *img;
+
+ intel->frame_buffer_texobj = obj =
+ ctx->Driver.NewTextureObject( ctx, (GLuint) -1, GL_TEXTURE_2D );
+
+ obj->MinFilter = GL_NEAREST;
+ obj->MagFilter = GL_NEAREST;
+
+ img = ctx->Driver.NewTextureImage( ctx );
+
+ _mesa_init_teximage_fields( ctx, GL_TEXTURE_2D, img,
+ region->pitch, region->height, 1, 0,
+ region->cpp == 4 ? GL_RGBA : GL_RGB );
+
+ _mesa_set_tex_image( obj, GL_TEXTURE_2D, 0, img );
+}
+
+void brw_FrameBufferTexDestroy( struct brw_context *brw )
+{
+ brw->intel.ctx.Driver.DeleteTexture( &brw->intel.ctx,
+ brw->intel.frame_buffer_texobj );
+}
diff --git a/src/mesa/drivers/dri/i965/brw_vtbl.c b/src/mesa/drivers/dri/i965/brw_vtbl.c
index 4896882034..ac09754e3a 100644
--- a/src/mesa/drivers/dri/i965/brw_vtbl.c
+++ b/src/mesa/drivers/dri/i965/brw_vtbl.c
@@ -72,6 +72,7 @@ static void brw_destroy_context( struct intel_context *intel )
brw_save_destroy( ctx );
brw_ProgramCacheDestroy( ctx );
+ brw_FrameBufferTexDestroy( brw );
}
/* called from intelDrawBuffer()
diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
index 5c7dc500ca..d24c618a66 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -239,6 +239,12 @@ static void upload_wm_surfaces(struct brw_context *brw )
brw->wm.bind.surf_ss_offset[i+1] = brw_cache_data( &brw->cache[BRW_SS_SURFACE], &surf );
brw->wm.nr_surfaces = i+2;
}
+ else if( texUnit->_ReallyEnabled &&
+ texUnit->_Current == intel->frame_buffer_texobj )
+ {
+ brw->wm.bind.surf_ss_offset[i+1] = brw->wm.bind.surf_ss_offset[0];
+ brw->wm.nr_surfaces = i+2;
+ }
else {
brw->wm.bind.surf_ss_offset[i+1] = 0;
}
diff --git a/src/mesa/drivers/dri/i965/intel_buffers.c b/src/mesa/drivers/dri/i965/intel_buffers.c
index d155c039d7..645ac8e4f9 100644
--- a/src/mesa/drivers/dri/i965/intel_buffers.c
+++ b/src/mesa/drivers/dri/i965/intel_buffers.c
@@ -235,7 +235,7 @@ static void intelClearWithTris(struct intel_context *intel,
{
- intel->vtbl.install_meta_state(intel);
+ intel->vtbl.install_meta_state(intel, META_FULL);
/* Get clear bounds after locking */
cx = ctx->DrawBuffer->_Xmin;
diff --git a/src/mesa/drivers/dri/i965/intel_context.h b/src/mesa/drivers/dri/i965/intel_context.h
index 2df8faef28..a8f7a61ba3 100644
--- a/src/mesa/drivers/dri/i965/intel_context.h
+++ b/src/mesa/drivers/dri/i965/intel_context.h
@@ -86,6 +86,11 @@ struct intel_texture_object
+/* Identifiers for use with install_meta_state below */
+enum
+{
+ META_FULL, META_VERTEX_ONLY
+};
struct intel_context
{
@@ -132,7 +137,8 @@ struct intel_context
/* Metaops:
*/
- void (*install_meta_state)( struct intel_context *intel );
+ void (*install_meta_state)( struct intel_context *intel,
+ GLenum state );
void (*leave_meta_state)( struct intel_context *intel );
void (*meta_draw_region)( struct intel_context *intel,
@@ -151,6 +157,8 @@ struct intel_context
void (*meta_no_stencil_write)( struct intel_context *intel );
void (*meta_no_depth_write)( struct intel_context *intel );
void (*meta_no_texture)( struct intel_context *intel );
+ void (*meta_frame_buffer_texture)( struct intel_context *intel,
+ GLint xoff, GLint yoff );
void (*meta_draw_quad)(struct intel_context *intel,
GLfloat x0, GLfloat x1,
@@ -218,6 +226,7 @@ struct intel_context
int drawY;
GLuint numClipRects; /* cliprects for that buffer */
drm_clip_rect_t *pClipRects;
+ struct gl_texture_object *frame_buffer_texobj;
GLboolean scissor;
drm_clip_rect_t draw_rect;
diff --git a/src/mesa/drivers/dri/i965/intel_pixel_copy.c b/src/mesa/drivers/dri/i965/intel_pixel_copy.c
index 55b58a8f67..0279311976 100644
--- a/src/mesa/drivers/dri/i965/intel_pixel_copy.c
+++ b/src/mesa/drivers/dri/i965/intel_pixel_copy.c
@@ -80,8 +80,6 @@ intel_check_blit_fragment_ops(GLcontext * ctx)
if (ctx->NewState)
_mesa_update_state(ctx);
- /* Could do logicop with the blitter:
- */
return !(ctx->_ImageTransferState ||
ctx->RenderMode != GL_RENDER ||
ctx->Color.AlphaEnabled ||
@@ -223,6 +221,65 @@ do_blit_copypixels(GLcontext * ctx,
return GL_TRUE;
}
+/**
+ * CopyPixels with metaops. We can support (most) fragment options that way.
+ */
+static GLboolean
+do_meta_copypixels(GLcontext * ctx,
+ GLint srcx, GLint srcy,
+ GLsizei width, GLsizei height,
+ GLint dstx, GLint dsty, GLenum type)
+{
+ struct intel_context *intel = intel_context(ctx);
+
+ /* We're going to cheat and use texturing to get the source region
+ * duplicated. Trying to cope with the case where texturing is
+ * already applied to fragments would be messy (and it's an unusual
+ * thing to want anyway), so we leave that to swrast.
+ *
+ * We don't want to worry about any case other than GL_COLOR, either
+ * (though we could, with a bit more work).
+ *
+ * PixelMap, PixelTransfer, PixelZoom etc. could also be handled with
+ * a bit more intelligence in metaops.
+ */
+ if( ctx->_ImageTransferState ||
+ ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F ||
+ ctx->RenderMode != GL_RENDER ||
+ ctx->Texture._EnabledUnits ||
+ ctx->FragmentProgram._Enabled ||
+ type != GL_COLOR )
+ return GL_FALSE;
+
+ /* We don't yet handle copying between two different buffers (which
+ * would really only require filling out a new surface state for
+ * the source instead of aliasing the draw one). Nor do we handle
+ * overlapping source/dest rectangles (since I assume there is no
+ * way to force the hardware to guarantee the drawing order that
+ * the GL specifies -- if so, the fastest approach might be to use
+ * the blitter to copy the source to a temporary surface and then
+ * map that back onto the destination). Of course, overlapping
+ * areas in different buffers would be fine.
+ */
+ if( ctx->Color.DrawBuffer[0] != ctx->ReadBuffer->ColorReadBuffer ||
+ ( abs( srcx - dstx ) < width && abs( srcy - dsty ) < height ) )
+ return GL_FALSE;
+
+ intel->vtbl.install_meta_state( intel, META_VERTEX_ONLY );
+
+ intel->vtbl.meta_frame_buffer_texture( intel, srcx - dstx, srcy - dsty );
+
+ intel->vtbl.meta_draw_quad( intel,
+ dstx, dstx + width,
+ dsty, dsty + height,
+ ctx->Current.RasterPos[ 2 ],
+ 0, 0, 0, 0, 0.0, 0.0, 0.0, 0.0 );
+
+ intel->vtbl.leave_meta_state( intel );
+
+ return GL_TRUE;
+}
+
void
intelCopyPixels(GLcontext * ctx,
GLint srcx, GLint srcy,
@@ -236,6 +293,12 @@ intelCopyPixels(GLcontext * ctx,
return;
if (INTEL_DEBUG & DEBUG_PIXEL)
+ _mesa_printf("fallback to do_meta_copypixels\n");
+
+ if (do_meta_copypixels(ctx, srcx, srcy, width, height, destx, desty, type))
+ return;
+
+ if (INTEL_DEBUG & DEBUG_PIXEL)
_mesa_printf("fallback to _swrast_CopyPixels\n");
_swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type);
diff --git a/src/mesa/drivers/dri/i965/intel_tex_validate.c b/src/mesa/drivers/dri/i965/intel_tex_validate.c
index 91ae0970a0..cb23b9dd87 100644
--- a/src/mesa/drivers/dri/i965/intel_tex_validate.c
+++ b/src/mesa/drivers/dri/i965/intel_tex_validate.c
@@ -133,6 +133,9 @@ GLuint intel_finalize_mipmap_tree( struct intel_context *intel,
GLuint nr_faces = 0;
struct gl_texture_image *firstImage;
+ if( tObj == intel->frame_buffer_texobj )
+ return GL_FALSE;
+
/* We know/require this is true by now:
*/
assert(intelObj->base.Complete);