mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-23 11:40:39 +02:00
Add accelerated CopyPixels for non-overlapping, 1:1 blits.
Submitted by Gary Wong <gtw@gnu.org>
This commit is contained in:
parent
716091a6a0
commit
3cd06cf8c5
10 changed files with 213 additions and 15 deletions
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ); */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue