Add accelerated CopyPixels for non-overlapping, 1:1 blits.

Submitted by Gary Wong <gtw@gnu.org>
This commit is contained in:
Eric Anholt 2006-11-29 01:16:12 +00:00
parent 716091a6a0
commit 3cd06cf8c5
10 changed files with 213 additions and 15 deletions

View file

@ -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.
*/

View file

@ -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

View file

@ -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 ); */
}

View file

@ -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 );
}

View file

@ -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()

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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");

View file

@ -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);