From 3cd06cf8c5ef6a27e36c584e12ba79ed8dacbf28 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 29 Nov 2006 01:16:12 +0000 Subject: [PATCH] Add accelerated CopyPixels for non-overlapping, 1:1 blits. Submitted by Gary Wong --- src/mesa/drivers/dri/i965/brw_context.c | 2 + src/mesa/drivers/dri/i965/brw_context.h | 6 +- src/mesa/drivers/dri/i965/brw_metaops.c | 98 +++++++++++++++++-- src/mesa/drivers/dri/i965/brw_tex.c | 32 ++++++ src/mesa/drivers/dri/i965/brw_vtbl.c | 1 + .../drivers/dri/i965/brw_wm_surface_state.c | 6 ++ src/mesa/drivers/dri/i965/intel_buffers.c | 2 +- src/mesa/drivers/dri/i965/intel_context.h | 11 ++- src/mesa/drivers/dri/i965/intel_pixel_copy.c | 67 ++++++++++++- .../drivers/dri/i965/intel_tex_validate.c | 3 + 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 c1f6617f3fd..bc422c1a50b 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 1137bfd2c76..a57c794834f 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 18ca7b13412..ca8e1d30805 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 + * frame buffer texture by Gary Wong */ @@ -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 8332d869e1d..c3ffa9e6577 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 4896882034b..ac09754e3ae 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 5c7dc500cab..d24c618a668 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 d155c039d77..645ac8e4f92 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 2df8faef28e..a8f7a61ba3b 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 55b58a8f670..0279311976e 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, @@ -235,6 +292,12 @@ intelCopyPixels(GLcontext * ctx, if (do_blit_copypixels(ctx, srcx, srcy, width, height, destx, desty, type)) 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"); diff --git a/src/mesa/drivers/dri/i965/intel_tex_validate.c b/src/mesa/drivers/dri/i965/intel_tex_validate.c index 91ae0970a04..cb23b9dd879 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); -- 2.30.2