Hi, attached is an updated version of the batched stretchblit.
All the code duplication of batched vs. non batched versions has been removed... Not sure how to best deal with the calling of dfb_gfxcard_blit( srect, drect->x, drect->y, state ); if the rectangle sizes match. Should dfb_state_check()/_acquire() maybe do DFXL_BLIT | DFXL_STRETCHBLIT in the first place, instead of releasing and releasing and reacquiring the STRETCHBLIT state? Cheers, Andre'
From 85cfa63c54985c9e08acb83aab19c995ba0d2086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Draszik?= <andre.dras...@st.com> Date: Tue, 4 Aug 2009 01:06:46 +0100 Subject: [PATCH] (surface) implement IDirectFBSurface::BatchStretchBlit() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: André Draszik <andre.dras...@st.com> --- include/directfb.h | 16 +++ proxy/dispatcher/idirectfbsurface_dispatcher.c | 50 +++++++++ proxy/dispatcher/idirectfbsurface_dispatcher.h | 1 + proxy/requestor/idirectfbsurface_requestor.c | 26 +++++ src/core/gfxcard.c | 133 +++++++++++++---------- src/core/gfxcard.h | 5 + src/display/idirectfbsurface.c | 135 +++++++++++++++--------- 7 files changed, 261 insertions(+), 105 deletions(-) diff --git a/include/directfb.h b/include/directfb.h index 7873b3b..cec8674 100644 --- a/include/directfb.h +++ b/include/directfb.h @@ -4253,6 +4253,22 @@ DEFINE_INTERFACE( IDirectFBSurface, const DFBTrapezoid *traps, unsigned int num ); + + /** Blitting functions **/ + + /* + * Blit a bunch of areas scaled from the source to the destination + * rectangles. + * + * <b>source_rects</b> and <b>dest_rects</b> will be modified! + */ + DFBResult (*BatchStretchBlit) ( + IDirectFBSurface *thiz, + IDirectFBSurface *source, + DFBRectangle *source_rects, + DFBRectangle *dest_rects, + int num + ); ) diff --git a/proxy/dispatcher/idirectfbsurface_dispatcher.c b/proxy/dispatcher/idirectfbsurface_dispatcher.c index 9701490..822ca8f 100644 --- a/proxy/dispatcher/idirectfbsurface_dispatcher.c +++ b/proxy/dispatcher/idirectfbsurface_dispatcher.c @@ -602,6 +602,21 @@ IDirectFBSurface_Dispatcher_StretchBlit( IDirectFBSurface *thiz, } static DFBResult +IDirectFBSurface_Dispatcher_BatchStretchBlit( IDirectFBSurface *thiz, + IDirectFBSurface *source, + DFBRectangle *source_rects, + DFBRectangle *destination_rects, + int num ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Dispatcher) + + if (!source) + return DFB_INVARG; + + return DFB_UNIMPLEMENTED; +} + +static DFBResult IDirectFBSurface_Dispatcher_TextureTriangles( IDirectFBSurface *thiz, IDirectFBSurface *source, const DFBVertex *vertices, @@ -1172,6 +1187,37 @@ Dispatch_StretchBlit( IDirectFBSurface *thiz, IDirectFBSurface *real, } static DirectResult +Dispatch_BatchStretchBlit( IDirectFBSurface *thiz, IDirectFBSurface *real, + VoodooManager *manager, VoodooRequestMessage *msg ) +{ + DirectResult ret; + VoodooMessageParser parser; + VoodooInstanceID instance; + unsigned int num; + const DFBRectangle *source_rects; + const DFBRectangle *dest_rects; + void *surface; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Dispatcher) + + VOODOO_PARSER_BEGIN( parser, msg ); + VOODOO_PARSER_GET_ID( parser, instance ); + VOODOO_PARSER_GET_UINT( parser, num ); + VOODOO_PARSER_GET_DATA( parser, source_rects ); + VOODOO_PARSER_GET_DATA( parser, dest_rects ); + VOODOO_PARSER_END( parser ); + + ret = voodoo_manager_lookup_local( manager, instance, NULL, &surface ); + if (ret) + return ret; + + real->BatchStretchBlit( real, surface, (DFBRectangle *) source_rects, + (DFBRectangle *) dest_rects, num ); + + return DFB_OK; +} + +static DirectResult Dispatch_TextureTriangles( IDirectFBSurface *thiz, IDirectFBSurface *real, VoodooManager *manager, VoodooRequestMessage *msg ) { @@ -1766,6 +1812,9 @@ Dispatch( void *dispatcher, void *real, VoodooManager *manager, VoodooRequestMes case IDIRECTFBSURFACE_METHOD_ID_StretchBlit: return Dispatch_StretchBlit( dispatcher, real, manager, msg ); + case IDIRECTFBSURFACE_METHOD_ID_BatchStretchBlit: + return Dispatch_BatchStretchBlit( dispatcher, real, manager, msg ); + case IDIRECTFBSURFACE_METHOD_ID_TextureTriangles: return Dispatch_TextureTriangles( dispatcher, real, manager, msg ); @@ -1899,6 +1948,7 @@ Construct( IDirectFBSurface *thiz, thiz->TileBlit = IDirectFBSurface_Dispatcher_TileBlit; thiz->BatchBlit = IDirectFBSurface_Dispatcher_BatchBlit; thiz->StretchBlit = IDirectFBSurface_Dispatcher_StretchBlit; + thiz->BatchStretchBlit = IDirectFBSurface_Dispatcher_BatchStretchBlit; thiz->TextureTriangles = IDirectFBSurface_Dispatcher_TextureTriangles; thiz->SetDrawingFlags = IDirectFBSurface_Dispatcher_SetDrawingFlags; diff --git a/proxy/dispatcher/idirectfbsurface_dispatcher.h b/proxy/dispatcher/idirectfbsurface_dispatcher.h index a04b9d8..dcc6eaf 100644 --- a/proxy/dispatcher/idirectfbsurface_dispatcher.h +++ b/proxy/dispatcher/idirectfbsurface_dispatcher.h @@ -87,5 +87,6 @@ #define IDIRECTFBSURFACE_METHOD_ID_Read 56 #define IDIRECTFBSURFACE_METHOD_ID_SetColors 57 #define IDIRECTFBSURFACE_METHOD_ID_BatchBlit2 58 +#define IDIRECTFBSURFACE_METHOD_ID_BatchStretchBlit 59 #endif diff --git a/proxy/requestor/idirectfbsurface_requestor.c b/proxy/requestor/idirectfbsurface_requestor.c index 30b37ca..aeaa524 100644 --- a/proxy/requestor/idirectfbsurface_requestor.c +++ b/proxy/requestor/idirectfbsurface_requestor.c @@ -924,6 +924,31 @@ IDirectFBSurface_Requestor_StretchBlit( IDirectFBSurface *thiz, } static DFBResult +IDirectFBSurface_Requestor_BatchStretchBlit( IDirectFBSurface *thiz, + IDirectFBSurface *source, + DFBRectangle *source_rects, + DFBRectangle *dest_rects, + int num ) +{ + IDirectFBSurface_Requestor_data *source_data; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Requestor) + + if (!source) + return DFB_INVARG; + + DIRECT_INTERFACE_GET_DATA_FROM( source, source_data, IDirectFBSurface_Requestor ); + + return voodoo_manager_request( data->manager, data->instance, + IDIRECTFBSURFACE_METHOD_ID_BatchStretchBlit, VREQ_QUEUE, NULL, + VMBT_ID, source_data->instance, + VMBT_UINT, num, + VMBT_DATA, num * sizeof(DFBRectangle), source_rects, + VMBT_DATA, num * sizeof(DFBRectangle), dest_rects, + VMBT_NONE ); +} + +static DFBResult IDirectFBSurface_Requestor_TextureTriangles( IDirectFBSurface *thiz, IDirectFBSurface *source, const DFBVertex *vertices, @@ -1574,6 +1599,7 @@ Construct( IDirectFBSurface *thiz, thiz->TileBlit = IDirectFBSurface_Requestor_TileBlit; thiz->BatchBlit = IDirectFBSurface_Requestor_BatchBlit; thiz->StretchBlit = IDirectFBSurface_Requestor_StretchBlit; + thiz->BatchStretchBlit = IDirectFBSurface_Requestor_BatchStretchBlit; thiz->TextureTriangles = IDirectFBSurface_Requestor_TextureTriangles; thiz->SetDrawingFlags = IDirectFBSurface_Requestor_SetDrawingFlags; diff --git a/src/core/gfxcard.c b/src/core/gfxcard.c index a8376a7..1f23150 100644 --- a/src/core/gfxcard.c +++ b/src/core/gfxcard.c @@ -2423,32 +2423,21 @@ void dfb_gfxcard_tileblit( DFBRectangle *rect, int dx1, int dy1, int dx2, int dy dfb_state_unlock( state ); } -void dfb_gfxcard_stretchblit( DFBRectangle *srect, DFBRectangle *drect, - CardState *state ) +void dfb_gfxcard_batchstretchblit( DFBRectangle *srects, + DFBRectangle *drects, + int num, CardState *state ) { - bool hw = false; + int i = 0; + + D_DEBUG_AT( Core_GraphicsOps, "%s( %p, %p [%d], %p )\n", __FUNCTION__, + srects, drects, num, state ); D_ASSERT( card != NULL ); D_ASSERT( card->shared != NULL ); D_MAGIC_ASSERT( state, CardState ); - D_ASSERT( srect != NULL ); - D_ASSERT( drect != NULL ); - - D_DEBUG_AT( Core_GraphicsOps, "%s( %d,%d - %dx%d -> %d,%d - %dx%d, %p )\n", - __FUNCTION__, DFB_RECTANGLE_VALS(srect), DFB_RECTANGLE_VALS(drect), state ); - - if (state->blittingflags & (DSBLIT_ROTATE90 | DSBLIT_ROTATE270)) { - if (srect->w == drect->h && srect->h == drect->w) { - dfb_gfxcard_blit( srect, drect->x, drect->y, state ); - return; - } - } - else { - if (srect->w == drect->w && srect->h == drect->h) { - dfb_gfxcard_blit( srect, drect->x, drect->y, state ); - return; - } - } + D_ASSERT( srects != NULL ); + D_ASSERT( drects != NULL ); + D_ASSERT( num > 0 ); /* The state is locked during graphics operations. */ dfb_state_lock( state ); @@ -2456,55 +2445,77 @@ void dfb_gfxcard_stretchblit( DFBRectangle *srect, DFBRectangle *drect, /* Signal beginning of sequence of operations if not already done. */ dfb_state_start_drawing( state, card ); - if (!(state->render_options & DSRO_MATRIX) && - !dfb_clip_blit_precheck( &state->clip, drect->w, drect->h, - drect->x, drect->y )) - { - dfb_state_unlock( state ); - return; - } - if (dfb_gfxcard_state_check( state, DFXL_STRETCHBLIT ) && dfb_gfxcard_state_acquire( state, DFXL_STRETCHBLIT )) { - if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) && - !D_FLAGS_IS_SET( card->caps.clip, DFXL_STRETCHBLIT )) - dfb_clip_stretchblit( &state->clip, srect, drect ); + bool need_clip = (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) + && !D_FLAGS_IS_SET( card->caps.clip, DFXL_STRETCHBLIT )); - hw = card->funcs.StretchBlit( card->driver_data, card->device_data, srect, drect ); + for (; i<num; i++) { + DFBRectangle * __restrict srect = &srects[i]; + DFBRectangle * __restrict drect = &drects[i]; + + D_DEBUG_AT( Core_GraphicsOps, + " -> %d,%d - %dx%d -> %d,%d - %dx%d\n", + __FUNCTION__, DFB_RECTANGLE_VALS(srect), + DFB_RECTANGLE_VALS(drect) ); + + if ((state->blittingflags & (DSBLIT_ROTATE90 | DSBLIT_ROTATE270) + && (srect->w == drect->h && srect->h == drect->w)) + || (srect->w == drect->w && srect->h == drect->h)) { + dfb_gfxcard_state_release( state ); + dfb_gfxcard_blit( srect, drect->x, drect->y, state ); + if (!dfb_gfxcard_state_check( state, DFXL_STRETCHBLIT ) + || !dfb_gfxcard_state_acquire( state, DFXL_STRETCHBLIT )) + break; + } + else if ((state->render_options & DSRO_MATRIX) + || dfb_clip_blit_precheck( &state->clip, drect->w, drect->h, + drect->x, drect->y )) { + if (need_clip) + dfb_clip_stretchblit( &state->clip, srect, drect ); + + if (!card->funcs.StretchBlit( card->driver_data, + card->device_data, + srect, drect )) + break; + } + } dfb_gfxcard_state_release( state ); } - if (!hw) { - if (state->render_options & DSRO_MATRIX) { - int x1, y1, x2, y2; + if (i < num) { + if (gAcquire( state, DFXL_STRETCHBLIT )) { + for (; i<num; i++) { + DFBRectangle * __restrict srect = &srects[i]; + DFBRectangle * __restrict drect = &drects[i]; - if (state->matrix[0] < 0 || state->matrix[1] != 0 || - state->matrix[3] != 0 || state->matrix[4] < 0 || - state->matrix[6] != 0 || state->matrix[7] != 0) { - D_WARN( "rotation not yet implemented" ); - dfb_state_unlock( state ); - return; - } + if (state->render_options & DSRO_MATRIX) { + int x1, y1, x2, y2; - x1 = drect->x; y1 = drect->y; - x2 = x1+drect->w; y2 = y1+drect->h; - DFB_TRANSFORM(x1, y1, state->matrix, state->affine_matrix); - DFB_TRANSFORM(x2, y2, state->matrix, state->affine_matrix); - drect->x = x1; drect->y = y1; - drect->w = x2-x1; drect->h = y2-y1; + if (state->matrix[0] < 0 || state->matrix[1] != 0 || + state->matrix[3] != 0 || state->matrix[4] < 0 || + state->matrix[6] != 0 || state->matrix[7] != 0) { + D_WARN( "rotation not yet implemented" ); + continue; + } - if (!dfb_clip_blit_precheck( &state->clip, - drect->w, drect->h, drect->x, drect->y )) { - dfb_state_unlock( state ); - return; + x1 = drect->x; y1 = drect->y; + x2 = x1+drect->w; y2 = y1+drect->h; + DFB_TRANSFORM(x1, y1, state->matrix, state->affine_matrix); + DFB_TRANSFORM(x2, y2, state->matrix, state->affine_matrix); + drect->x = x1; drect->y = y1; + drect->w = x2-x1; drect->h = y2-y1; + + if (!dfb_clip_blit_precheck( &state->clip, + drect->w, drect->h, drect->x, drect->y )) + continue; + } + + gStretchBlit( state, srect, drect ); } - } - if (gAcquire( state, DFXL_STRETCHBLIT )) { - /* Clipping is performed in the following function. */ - gStretchBlit( state, srect, drect ); gRelease( state ); } } @@ -2512,6 +2523,14 @@ void dfb_gfxcard_stretchblit( DFBRectangle *srect, DFBRectangle *drect, dfb_state_unlock( state ); } +void dfb_gfxcard_stretchblit( DFBRectangle *srect, DFBRectangle *drect, + CardState *state ) +{ + D_ONCE ("dfb_gfxcard_batchstretchblit() should be used!"); + + dfb_gfxcard_batchstretchblit( srect, drect, 1, state); +} + void dfb_gfxcard_texture_triangles( DFBVertex *vertices, int num, DFBTriangleFormation formation, CardState *state ) diff --git a/src/core/gfxcard.h b/src/core/gfxcard.h index 6c427b3..8075fa9 100644 --- a/src/core/gfxcard.h +++ b/src/core/gfxcard.h @@ -381,6 +381,11 @@ void dfb_gfxcard_stretchblit ( DFBRectangle *srect, DFBRectangle *drect, CardState *state ); +void dfb_gfxcard_batchstretchblit ( DFBRectangle *srects, + DFBRectangle *drects, + int num, + CardState *state ); + void dfb_gfxcard_texture_triangles ( DFBVertex *vertices, int num, DFBTriangleFormation formation, diff --git a/src/display/idirectfbsurface.c b/src/display/idirectfbsurface.c index 55a95e0..967cbbe 100644 --- a/src/display/idirectfbsurface.c +++ b/src/display/idirectfbsurface.c @@ -2064,18 +2064,54 @@ IDirectFBSurface_BatchBlit2( IDirectFBSurface *thiz, return DFB_OK; } +static bool +clip_StretchBlit( DFBRectangle * __restrict src, + const DFBRectangle * __restrict current_area_src, + DFBRectangle * __restrict dst ) +{ + DFBRectangle orig_src = *src; + + if (!dfb_rectangle_intersect( src, current_area_src )) { + src->w = src->h = 0; + dst->w = dst->h = 0; + return false; + } + + /* clipping of the source rectangle must be applied to the destination */ + if (src->x != orig_src.x) + dst->x += (int)( (src->x - orig_src.x) * + (dst->w / (float)orig_src.w) + 0.5f); + + if (src->y != orig_src.y) + dst->y += (int)( (src->y - orig_src.y) * + (dst->h / (float)orig_src.h) + 0.5f); + + if (src->w != orig_src.w) + dst->w = D_ICEIL(dst->w * (src->w / (float)orig_src.w)); + + if (src->h != orig_src.h) + dst->h = D_ICEIL(dst->h * (src->h / (float)orig_src.h)); + + D_DEBUG_AT( Surface, " -> [%2d] %4d,%4d-%4dx%4d <- %4d,%4d-%4dx%4d\n", + 0, dst->x, dst->y, dst->w, dst->h, + src->x, src->y, src->w, src->h ); + + return true; +} + static DFBResult -IDirectFBSurface_StretchBlit( IDirectFBSurface *thiz, - IDirectFBSurface *source, - const DFBRectangle *source_rect, - const DFBRectangle *destination_rect ) +IDirectFBSurface_BatchStretchBlit( IDirectFBSurface *thiz, + IDirectFBSurface *source, + DFBRectangle *source_rects, + DFBRectangle *dest_rects, + int num ) { - DFBRectangle srect, drect; IDirectFBSurface_data *src_data; + int i; DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) - D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + D_DEBUG_AT( Surface, "%s( %p, %d )\n", __FUNCTION__, thiz, num ); if (!data->surface) return DFB_DESTROYED; @@ -2087,7 +2123,7 @@ IDirectFBSurface_StretchBlit( IDirectFBSurface *thiz, if (data->locked) return DFB_LOCKED; - if (!source) + if (!source || !source_rects || !dest_rects || num < 1) return DFB_INVARG; @@ -2097,52 +2133,26 @@ IDirectFBSurface_StretchBlit( IDirectFBSurface *thiz, return DFB_INVAREA; - /* do destination rectangle */ - if (destination_rect) { - if (destination_rect->w < 1 || destination_rect->h < 1) - return DFB_INVARG; - - drect = *destination_rect; + for (i=0; i<num; i++) { + DFBRectangle * __restrict src = &source_rects[i]; + DFBRectangle * __restrict dst = &dest_rects[i]; - drect.x += data->area.wanted.x; - drect.y += data->area.wanted.y; - } - else - drect = data->area.wanted; + if (dst->w < 1 || dst->h < 1) { + dst->w = 0; + dst->h = 0; + continue; + } - /* do source rectangle */ - if (source_rect) { - if (source_rect->w < 1 || source_rect->h < 1) + if (src->w < 1 || src->h < 1) return DFB_INVARG; - srect = *source_rect; + src->x += src_data->area.wanted.x; + src->y += src_data->area.wanted.y; - srect.x += src_data->area.wanted.x; - srect.y += src_data->area.wanted.y; - } - else - srect = src_data->area.wanted; - - - /* clipping of the source rectangle must be applied to the destination */ - { - DFBRectangle orig_src = srect; - - if (!dfb_rectangle_intersect( &srect, &src_data->area.current )) - return DFB_INVAREA; + dst->x += data->area.wanted.x; + dst->y += data->area.wanted.y; - if (srect.x != orig_src.x) - drect.x += (int)( (srect.x - orig_src.x) * - (drect.w / (float)orig_src.w) + 0.5f); - - if (srect.y != orig_src.y) - drect.y += (int)( (srect.y - orig_src.y) * - (drect.h / (float)orig_src.h) + 0.5f); - - if (srect.w != orig_src.w) - drect.w = D_ICEIL(drect.w * (srect.w / (float)orig_src.w)); - if (srect.h != orig_src.h) - drect.h = D_ICEIL(drect.h * (srect.h / (float)orig_src.h)); + clip_StretchBlit( src, &src_data->area.current, dst ); } dfb_state_set_source( &data->state, src_data->surface ); @@ -2151,11 +2161,39 @@ IDirectFBSurface_StretchBlit( IDirectFBSurface *thiz, if (data->state.blittingflags & DSBLIT_SRC_COLORKEY) dfb_state_set_src_colorkey( &data->state, src_data->src_key.value ); - dfb_gfxcard_stretchblit( &srect, &drect, &data->state ); + dfb_gfxcard_batchstretchblit( source_rects, dest_rects, num, + &data->state ); return DFB_OK; } +static DFBResult +IDirectFBSurface_StretchBlit( IDirectFBSurface *thiz, + IDirectFBSurface *source, + const DFBRectangle *source_rect, + const DFBRectangle *destination_rect ) +{ + DFBRectangle srect, drect; + + if (destination_rect) + drect = *destination_rect; + else { + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + drect = (DFBRectangle) { 0, 0, data->area.wanted.w, data->area.wanted.h }; + } + + if (source_rect) + srect = *source_rect; + else { + IDirectFBSurface_data *sd = (IDirectFBSurface_data*)source->priv; + + srect = (DFBRectangle) { 0, 0, sd->area.wanted.w, sd->area.wanted.h }; + } + + return IDirectFBSurface_BatchStretchBlit( thiz, source, &srect, &drect, 1 ); +} + #define SET_VERTEX(v,X,Y,Z,W,S,T) \ do { \ (v)->x = X; \ @@ -2924,6 +2962,7 @@ DFBResult IDirectFBSurface_Construct( IDirectFBSurface *thiz, thiz->BatchBlit = IDirectFBSurface_BatchBlit; thiz->BatchBlit2 = IDirectFBSurface_BatchBlit2; thiz->StretchBlit = IDirectFBSurface_StretchBlit; + thiz->BatchStretchBlit = IDirectFBSurface_BatchStretchBlit; thiz->TextureTriangles = IDirectFBSurface_TextureTriangles; thiz->SetDrawingFlags = IDirectFBSurface_SetDrawingFlags; -- 1.7.1
_______________________________________________ directfb-dev mailing list directfb-dev@directfb.org http://mail.directfb.org/cgi-bin/mailman/listinfo/directfb-dev