Beispiel #1
0
void
dfb_state_update_sources( CardState *state, CardStateFlags flags )
{
     D_DEBUG_AT( Core_GfxState, "%s( %p )\n", __FUNCTION__, state );

     D_MAGIC_ASSERT( state, CardState );
     DFB_REGION_ASSERT( &state->clip );

     if (D_FLAGS_IS_SET( state->flags & flags, CSF_SOURCE )) {
          CoreSurface *source = state->source;

          D_ASSERT( source != NULL );

          if (direct_serial_update( &state->src_serial, &source->serial ))
               state->modified |= SMF_SOURCE;
     }

     if (D_FLAGS_IS_SET( state->flags & flags, CSF_SOURCE_MASK )) {
          CoreSurface *source_mask = state->source_mask;

          D_ASSERT( source_mask != NULL );

          if (direct_serial_update( &state->src_mask_serial, &source_mask->serial ))
               state->modified |= SMF_SOURCE_MASK;
     }

     if (D_FLAGS_IS_SET( state->flags & flags, CSF_SOURCE2 )) {
          CoreSurface *source2 = state->source2;

          D_ASSERT( source2 != NULL );

          if (direct_serial_update( &state->src2_serial, &source2->serial ))
               state->modified |= SMF_SOURCE2;
     }
}
Beispiel #2
0
void
dfb_updates_add( DFBUpdates      *updates,
                 const DFBRegion *region )
{
     int i;

     D_MAGIC_ASSERT( updates, DFBUpdates );
     DFB_REGION_ASSERT( region );
     D_ASSERT( updates->regions != NULL );
     D_ASSERT( updates->num_regions >= 0 );
     D_ASSERT( updates->num_regions <= updates->max_regions );

     D_DEBUG_AT( DFB_Updates, "%s( %p, %4d,%4d-%4dx%4d )\n", __FUNCTION__, (void*)updates,
                 DFB_RECTANGLE_VALS_FROM_REGION(region) );

     if (updates->num_regions == 0) {
          D_DEBUG_AT( DFB_Updates, "  -> added as first\n" );

          updates->regions[0]  = updates->bounding = *region;
          updates->num_regions = 1;

          return;
     }

     for (i=0; i<updates->num_regions; i++) {
          if (dfb_region_region_extends( &updates->regions[i], region ) ||
              dfb_region_region_intersects( &updates->regions[i], region ))
          {
               D_DEBUG_AT( DFB_Updates, "  -> combined with [%d] %4d,%4d-%4dx%4d\n", i,
                           DFB_RECTANGLE_VALS_FROM_REGION(&updates->regions[i]) );

               dfb_region_region_union( &updates->regions[i], region );

               dfb_region_region_union( &updates->bounding, region );

               D_DEBUG_AT( DFB_Updates, "  -> resulting in  [%d] %4d,%4d-%4dx%4d\n", i,
                           DFB_RECTANGLE_VALS_FROM_REGION(&updates->regions[i]) );

               return;
          }
     }

     if (updates->num_regions == updates->max_regions) {
          dfb_region_region_union( &updates->bounding, region );

          updates->regions[0]  = updates->bounding;
          updates->num_regions = 1;

          D_DEBUG_AT( DFB_Updates, "  -> collapsing to [0] %4d,%4d-%4dx%4d\n",
                      DFB_RECTANGLE_VALS_FROM_REGION(&updates->regions[0]) );
     }
     else {
          updates->regions[updates->num_regions++] = *region;

          dfb_region_region_union( &updates->bounding, region );

          D_DEBUG_AT( DFB_Updates, "  -> added as      [%d] %4d,%4d-%4dx%4d\n", updates->num_regions - 1,
                      DFB_RECTANGLE_VALS_FROM_REGION(&updates->regions[updates->num_regions - 1]) );
     }
}
Beispiel #3
0
void
dfb_state_update_destination( CardState *state )
{
     CoreSurface *destination;

     D_DEBUG_AT( Core_GfxState, "%s( %p )\n", __FUNCTION__, state );

     D_MAGIC_ASSERT( state, CardState );
     DFB_REGION_ASSERT( &state->clip );

     destination = state->destination;

     if (D_FLAGS_IS_SET( state->flags, CSF_DESTINATION )) {
          D_DEBUG_AT( Core_GfxState, "  -> CSF_DESTINATION is set\n" );

          D_ASSERT( destination != NULL );

          if (direct_serial_update( &state->dst_serial, &destination->serial )) {
               D_DEBUG_AT( Core_GfxState, "  -> serial is updated\n" );

               validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, true );

               state->modified |= SMF_DESTINATION;
          }
     }
     else if (destination)
          validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, true );
}
Beispiel #4
0
void
dfb_gfx_copy_regions_stereo( CoreSurface           *source,
                             CoreSurfaceBufferRole  from,
                             DFBSurfaceStereoEye    source_eye,
                             CoreSurface           *destination,
                             CoreSurfaceBufferRole  to,
                             DFBSurfaceStereoEye    destination_eye,
                             const DFBRegion       *regions,
                             unsigned int           num,
                             int                    x,
                             int                    y )
{
     unsigned int i, n = 0;
     DFBRectangle rect = { 0, 0, source->config.size.w, source->config.size.h };
     DFBRectangle rects[num];
     DFBPoint     points[num];

     D_ASSERT( !dfb_config->task_manager );

     for (i=0; i<num; i++) {
          DFB_REGION_ASSERT( &regions[i] );

          rects[n] = DFB_RECTANGLE_INIT_FROM_REGION( &regions[i] );

          if (dfb_rectangle_intersect( &rects[n], &rect )) {
               points[n].x = x + rects[n].x - rect.x;
               points[n].y = y + rects[n].y - rect.y;

               n++;
          }
     }

     if (n > 0) {
          StateClient *client = state_client_tls.Get();

          D_FLAGS_SET( client->state.modified, SMF_CLIP | SMF_SOURCE | SMF_DESTINATION | SMF_FROM | SMF_TO );

          client->state.clip.x2     = destination->config.size.w - 1;
          client->state.clip.y2     = destination->config.size.h - 1;
          client->state.source      = source;
          client->state.destination = destination;
          client->state.from        = from;
          client->state.from_eye    = source_eye;
          client->state.to          = to;
          client->state.to_eye      = destination_eye;

          CoreGraphicsStateClient_Blit( &client->client, rects, points, n );

          CoreGraphicsStateClient_Flush( &client->client, 0, CGSCFF_NONE );

          /* Signal end of sequence. */
          dfb_state_stop_drawing( &client->state );

          client->state.destination = NULL;
          client->state.source      = NULL;
     }
}
Beispiel #5
0
void
dfb_gfx_copy_regions( CoreSurface           *source,
                      CoreSurfaceBufferRole  from,
                      CoreSurface           *destination,
                      CoreSurfaceBufferRole  to,
                      const DFBRegion       *regions,
                      unsigned int           num,
                      int                    x,
                      int                    y )
{
     unsigned int i, n = 0;
     DFBRectangle rect = { 0, 0, source->config.size.w, source->config.size.h };
     DFBRectangle rects[num];
     DFBPoint     points[num];

     for (i=0; i<num; i++) {
          DFB_REGION_ASSERT( &regions[i] );

          rects[n] = DFB_RECTANGLE_INIT_FROM_REGION( &regions[i] );

          if (dfb_rectangle_intersect( &rects[n], &rect )) {
               points[n].x = x + rects[n].x - rect.x;
               points[n].y = y + rects[n].y - rect.y;

               n++;
          }
     }

     if (n > 0) {
          pthread_mutex_lock( &copy_lock );

          if (!copy_state_inited) {
               dfb_state_init( &copy_state, NULL );
               copy_state_inited = true;
          }

          copy_state.modified   |= SMF_CLIP | SMF_SOURCE | SMF_DESTINATION;

          copy_state.clip.x2     = destination->config.size.w - 1;
          copy_state.clip.y2     = destination->config.size.h - 1;
          copy_state.source      = source;
          copy_state.destination = destination;
          copy_state.from        = from;
          copy_state.to          = to;

          dfb_gfxcard_batchblit( rects, points, n, &copy_state );
     
          /* Signal end of sequence. */
          dfb_state_stop_drawing( &copy_state );

          pthread_mutex_unlock( &copy_lock );
     }
}
Beispiel #6
0
void
dfb_state_update( CardState *state, bool update_sources )
{
     CoreSurface *destination;

     D_MAGIC_ASSERT( state, CardState );
     DFB_REGION_ASSERT( &state->clip );

     destination = state->destination;

     if (D_FLAGS_IS_SET( state->flags, CSF_DESTINATION )) {

          D_ASSERT( destination != NULL );

          if (direct_serial_update( &state->dst_serial, &destination->serial )) {
               validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, true );

               state->modified |= SMF_DESTINATION;
          }
     }
     else if (destination)
          validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, true );

     if (update_sources && D_FLAGS_IS_SET( state->flags, CSF_SOURCE )) {
          CoreSurface *source = state->source;

          D_ASSERT( source != NULL );

          if (direct_serial_update( &state->src_serial, &source->serial ))
               state->modified |= SMF_SOURCE;
     }

     if (update_sources && D_FLAGS_IS_SET( state->flags, CSF_SOURCE_MASK )) {
          CoreSurface *source_mask = state->source_mask;

          D_ASSERT( source_mask != NULL );

          if (direct_serial_update( &state->src_mask_serial, &source_mask->serial ))
               state->modified |= SMF_SOURCE_MASK;
     }

     if (update_sources && D_FLAGS_IS_SET( state->flags, CSF_SOURCE2 )) {
          CoreSurface *source2 = state->source2;

          D_ASSERT( source2 != NULL );

          if (direct_serial_update( &state->src2_serial, &source2->serial ))
               state->modified |= SMF_SOURCE2;
     }
}
Beispiel #7
0
void
dfb_updates_add( DFBUpdates      *updates,
                 const DFBRegion *region )
{
     int i;

     D_MAGIC_ASSERT( updates, DFBUpdates );
     DFB_REGION_ASSERT( region );
     D_ASSERT( updates->regions != NULL );
     D_ASSERT( updates->num_regions >= 0 );
     D_ASSERT( updates->num_regions <= updates->max_regions );

     if (updates->num_regions == 0) {
          updates->regions[0]  = updates->bounding = *region;
          updates->num_regions = 1;

          return;
     }

     for (i=0; i<updates->num_regions; i++) {
          DFBRegion inter = updates->regions[i];

          if (dfb_region_region_intersect( &inter, region )) {
               DFBRegion uni = updates->regions[i];

               dfb_region_region_union( &uni, region );

               updates->regions[i] = uni;

               dfb_region_region_union( &updates->bounding, &uni );

               return;
          }
     }

     if (updates->num_regions == updates->max_regions) {
          dfb_region_region_union( &updates->bounding, region );

          updates->regions[0]  = updates->bounding;
          updates->num_regions = 1;
     }
     else {
          updates->regions[updates->num_regions++] = *region;

          dfb_region_region_union( &updates->bounding, region );
     }
}
Beispiel #8
0
static DFBResult
dfb_x11_update_screen( DFBX11 *x11, const DFBRegion *region, CoreSurfaceBufferLock *lock )
{
     int           ret;
     DFBX11Shared *shared = x11->shared;

     DFB_REGION_ASSERT( region );
     D_ASSERT( lock != NULL );

     /* FIXME: Just a hot fix! */
     while (shared->update.lock)
          usleep( 10000 );

     shared->update.region = *region;
     shared->update.lock   = lock;

     if (fusion_call_execute( &shared->call, FCEF_NONE, X11_UPDATE_SCREEN, &shared->update, &ret ))
          return DFB_FUSION;

     return ret;
}
Beispiel #9
0
static inline void
validate_clip( CardState *state,
               int        xmax,
               int        ymax,
               bool       warn )
{
     D_DEBUG_AT( Core_GfxState, "%s( %p, %d, %d, %d )\n", __FUNCTION__, state, xmax, ymax, warn );

     D_MAGIC_ASSERT( state, CardState );
     DFB_REGION_ASSERT( &state->clip );

     D_ASSERT( xmax >= 0 );
     D_ASSERT( ymax >= 0 );
     D_ASSERT( state->clip.x1 <= state->clip.x2 );
     D_ASSERT( state->clip.y1 <= state->clip.y2 );

     if (state->clip.x1 <= xmax &&
         state->clip.y1 <= ymax &&
         state->clip.x2 <= xmax &&
         state->clip.y2 <= ymax)
          return;

     if (warn)
          D_WARN( "Clip %d,%d-%dx%d invalid, adjusting to fit %dx%d",
                  DFB_RECTANGLE_VALS_FROM_REGION( &state->clip ), xmax+1, ymax+1 );

     if (state->clip.x1 > xmax)
          state->clip.x1 = xmax;

     if (state->clip.y1 > ymax)
          state->clip.y1 = ymax;

     if (state->clip.x2 > xmax)
          state->clip.x2 = xmax;

     if (state->clip.y2 > ymax)
          state->clip.y2 = ymax;

     state->modified |= SMF_CLIP;
}
Beispiel #10
0
static DFBResult
wm_update_stack( CoreWindowStack     *stack,
                 void                *wm_data,
                 void                *stack_data,
                 const DFBRegion     *region,
                 DFBSurfaceFlipFlags  flags )
{
     StackData *data = stack_data;

     D_ASSERT( stack != NULL );
     D_ASSERT( wm_data != NULL );
     D_ASSERT( stack_data != NULL );

     DFB_REGION_ASSERT( region );

     D_MAGIC_ASSERT( data, StackData );

     if (!data->context)
          return DFB_DESTROYED;

     return unique_context_update( data->context, region, 1, flags );
}
Beispiel #11
0
void
dfb_gfx_copy_regions_client( CoreSurface             *source,
                             CoreSurfaceBufferRole    from,
                             DFBSurfaceStereoEye      source_eye,
                             CoreSurface             *destination,
                             CoreSurfaceBufferRole    to,
                             DFBSurfaceStereoEye      destination_eye,
                             const DFBRegion         *regions,
                             unsigned int             num,
                             int                      x,
                             int                      y,
                             CoreGraphicsStateClient *_client )
{
     unsigned int             i, n = 0;
     DFBRectangle             rect = { 0, 0, source->config.size.w, source->config.size.h };
     DFBRectangle             rects[num];
     DFBPoint                 points[num];
     CoreGraphicsStateClient *client = _client ? _client : &state_client_tls.Get()->client;
     CardState               *state  = client->state;
     CardState                backup;

     for (i=0; i<num; i++) {
          DFB_REGION_ASSERT( &regions[i] );

          rects[n] = DFB_RECTANGLE_INIT_FROM_REGION( &regions[i] );

          if (dfb_rectangle_intersect( &rects[n], &rect )) {
               points[n].x = x + rects[n].x;
               points[n].y = y + rects[n].y;

               n++;
          }
     }

     if (n > 0) {
          backup.clip          = state->clip;
          backup.source        = state->source;
          backup.destination   = state->destination;
          backup.from          = state->from;
          backup.from_eye      = state->from_eye;
          backup.to            = state->to;
          backup.to_eye        = state->to_eye;
          backup.blittingflags = state->blittingflags;


          D_FLAGS_SET( state->modified, SMF_CLIP | SMF_SOURCE | SMF_DESTINATION | SMF_FROM | SMF_TO | SMF_BLITTING_FLAGS );

          state->clip.x1     = 0;
          state->clip.y1     = 0;
          state->clip.x2     = destination->config.size.w - 1;
          state->clip.y2     = destination->config.size.h - 1;
          state->source      = source;
          state->destination = destination;
          state->from        = from;
          state->from_eye    = source_eye;
          state->to          = to;
          state->to_eye      = destination_eye;
          state->blittingflags = DSBLIT_NOFX;

          CoreGraphicsStateClient_Blit( client, rects, points, n );

          if (!_client)
               CoreGraphicsStateClient_Flush( client, 0, CGSCFF_NONE );

          D_FLAGS_SET( state->modified, SMF_CLIP | SMF_SOURCE | SMF_DESTINATION | SMF_FROM | SMF_TO | SMF_BLITTING_FLAGS );

          state->clip          = backup.clip;
          state->source        = backup.source;
          state->destination   = backup.destination;
          state->from          = backup.from;
          state->from_eye      = backup.from_eye;
          state->to            = backup.to;
          state->to_eye        = backup.to_eye;
          state->blittingflags = backup.blittingflags;
     }
}
Beispiel #12
0
static void
draw_window( SaWManTier   *tier,
             SaWManWindow *sawwin,
             SaWManWindow *sawwin2,
             CardState    *state,
             DFBRegion    *region,
             bool          alpha_channel,
             bool          right_eye )
{
     SaWMan                  *sawman;
     CoreWindow              *window;
     DFBSurfaceBlittingFlags  flags = DSBLIT_NOFX;
     DFBRectangle             dst;
     DFBRectangle             src;
     DFBRegion                clip;
     DFBRegion                old_clip;
     int                      offset;

     D_MAGIC_ASSERT( sawwin,  SaWManWindow );
     D_MAGIC_ASSERT( state, CardState );
     DFB_REGION_ASSERT( region );

     sawman = sawwin->sawman;
     window = sawwin->window;
     dst    = sawwin->dst;
     src    = sawwin->src;

     D_MAGIC_ASSERT( sawman, SaWMan );
     D_ASSERT( window != NULL );
     D_ASSERT( window->surface != NULL );

     D_DEBUG_AT( SaWMan_Draw, "%s( %p, %d,%d-%dx%d )\n", __FUNCTION__,
                 sawwin, DFB_RECTANGLE_VALS_FROM_REGION( region ) );

     if (window->config.options & DWOP_STEREO_SIDE_BY_SIDE_HALF) {
          src.x /= 2;
          src.w /= 2;

          if (right_eye)
               src.x += window->surface->config.size.w / 2;
     }

     /* Modify dst for stereo offset. */
     offset = window->config.z;
     offset *= right_eye ? -1 : 1;
     dfb_rectangle_translate( &dst, offset, 0 );

     /* Setup clipping region. */
     clip = *region;

     if (!dfb_region_rectangle_intersect( &clip, &dst ))
          return;


     sawman_dispatch_blit( sawman, sawwin, right_eye, &sawwin->src, &dst, &clip );

     if (sawwin2)
          sawman_dispatch_blit( sawman, sawwin2, right_eye, &sawwin2->src, &dst, &clip );


     /* Backup clipping region. */
     old_clip = state->clip;

     /* Use per pixel alpha blending. */
     if (alpha_channel && (window->config.options & DWOP_ALPHACHANNEL))
          flags |= DSBLIT_BLEND_ALPHACHANNEL;

     /* Use global alpha blending. */
     if (window->config.opacity != 0xFF) {
          flags |= DSBLIT_BLEND_COLORALPHA;

          if (window->surface->config.caps & DSCAPS_PREMULTIPLIED) {
               /* Need to premultiply source with Ac? */
               flags |= DSBLIT_SRC_PREMULTCOLOR;

               dfb_state_set_src_blend( state, DSBF_ONE );
          }
          else
               dfb_state_set_src_blend( state, DSBF_SRCALPHA );

          /* Set opacity as blending factor. */
          if (state->color.a != window->config.opacity) {
               state->color.a   = window->config.opacity;
               state->modified |= SMF_COLOR;
          }
     }

     /* if we specified some kind of color, we will colorise. no DWCAPS_COLOR here. */
     if (window->config.color.a != 0) {
          DFBColor c;

          flags |= DSBLIT_COLORIZE;

          c   = window->config.color;
          c.a = state->color.a;

          if (! DFB_COLOR_EQUAL( c, state->color )) {
               state->color     = c;
               state->modified |= SMF_COLOR;
          }
     }

     /* Use source color keying. */
     if (window->config.options & DWOP_COLORKEYING) {
          flags |= DSBLIT_SRC_COLORKEY;

          D_DEBUG_AT( SaWMan_Draw, "  -> key 0x%08x\n", window->config.color_key );

          /* Set window color key. */
          dfb_state_set_src_colorkey( state, window->config.color_key );
     }

     /* Use automatic deinterlacing. */
     if (window->surface->config.caps & DSCAPS_INTERLACED)
          flags |= DSBLIT_DEINTERLACE;

     /* Different compositing methods depending on destination format. */
     if (flags & DSBLIT_BLEND_ALPHACHANNEL) {
          if (DFB_PIXELFORMAT_HAS_ALPHA( state->destination->config.format )) {
               /*
                * Always use compliant Porter/Duff SRC_OVER,
                * if the destination has an alpha channel.
                *
                * Cd = destination color  (non-premultiplied)
                * Ad = destination alpha
                *
                * Cs = source color       (non-premultiplied)
                * As = source alpha
                *
                * Ac = color alpha
                *
                * cd = Cd * Ad            (premultiply destination)
                * cs = Cs * As            (premultiply source)
                *
                * The full equation to calculate resulting color and alpha (premultiplied):
                *
                * cx = cd * (1-As*Ac) + cs * Ac
                * ax = Ad * (1-As*Ac) + As * Ac
                */
               dfb_state_set_src_blend( state, DSBF_ONE );

               /* Need to premultiply source with As*Ac or only with Ac? */
               if (! (window->surface->config.caps & DSCAPS_PREMULTIPLIED))
                    flags |= DSBLIT_SRC_PREMULTIPLY;
               else if (flags & DSBLIT_BLEND_COLORALPHA)
                    flags |= DSBLIT_SRC_PREMULTCOLOR;

               /* Need to premultiply/demultiply destination? */
//               if (! (state->destination->caps & DSCAPS_PREMULTIPLIED))
//                    flags |= DSBLIT_DST_PREMULTIPLY | DSBLIT_DEMULTIPLY;
          }
          else {
               /*
                * We can avoid DSBLIT_SRC_PREMULTIPLY for destinations without an alpha channel
                * by using another blending function, which is more likely that it's accelerated
                * than premultiplication at this point in time.
                *
                * This way the resulting alpha (ax) doesn't comply with SRC_OVER,
                * but as the destination doesn't have an alpha channel it's no problem.
                *
                * As the destination's alpha value is always 1.0 there's no need for
                * premultiplication. The resulting alpha value will also be 1.0 without
                * exceptions, therefore no need for demultiplication.
                *
                * cx = Cd * (1-As*Ac) + Cs*As * Ac  (still same effect as above)
                * ax = Ad * (1-As*Ac) + As*As * Ac  (wrong, but discarded anyways)
                */
               if (window->surface->config.caps & DSCAPS_PREMULTIPLIED) {
                    /* Need to premultiply source with Ac? */
                    if (flags & DSBLIT_BLEND_COLORALPHA)
                         flags |= DSBLIT_SRC_PREMULTCOLOR;

                    dfb_state_set_src_blend( state, DSBF_ONE );
               }
               else
                    dfb_state_set_src_blend( state, DSBF_SRCALPHA );
          }
     }

     /* Use color (key) protection if layer is keyed. */
     if (tier->context->config.options & DLOP_SRC_COLORKEY) {
          flags |= DSBLIT_COLORKEY_PROTECT;

          dfb_state_set_colorkey( state, &tier->key );
     }

     /* Set blitting flags. */
     dfb_state_set_blitting_flags( state, flags );

     /* Set render options. */
     if (sawman->scaling_mode == SWMSM_SMOOTH)
          dfb_state_set_render_options( state, DSRO_SMOOTH_DOWNSCALE | DSRO_SMOOTH_UPSCALE );
     else
          dfb_state_set_render_options( state, DSRO_NONE );

     /* Set blitting source. */
     state->source    = window->surface;
     state->from_eye  = (right_eye && (sawwin->caps & DWCAPS_STEREO)) ? DSSE_RIGHT : DSSE_LEFT;
     state->modified |= SMF_SOURCE | SMF_FROM;

     D_DEBUG_AT( SaWMan_Draw, "  [][] %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS_FROM_REGION( &clip ) );

     /* Change clipping region. */
     dfb_state_set_clip( state, &clip );

     D_DEBUG_AT( SaWMan_Draw, "    => %4d,%4d-%4dx%4d <- %4d,%4d-%4dx%4d\n",
                 DFB_RECTANGLE_VALS( &dst ), DFB_RECTANGLE_VALS( &src ) );

#ifndef OLD_COREWINDOWS_STRUCTURE
     if (sawwin2) {
          CoreWindow   *window2;
          DFBRectangle *src2;
          DFBPoint      p1,p2,p;

          D_MAGIC_ASSERT( sawwin2, SaWManWindow );
          window2 = sawwin2->window;
          D_ASSERT( window2 != NULL );
          D_ASSERT( window2->surface != NULL );
          src2 = &sawwin2->src;

          state->source2  = window2->surface;
          state->modified = SMF_SOURCE2;

          p1.x = src2->x + (sawwin->dst.x - sawwin2->dst.x);
          p1.y = src2->y + (sawwin->dst.y - sawwin2->dst.y);
          p2.x = sawwin->dst.x;
          p2.y = sawwin->dst.y;

          p.x = p1.x;
          p.y = p1.y;

          p1.x = src.x;
          p1.y = src.y;

          src.x = p.x;
          src.y = p.y;

          CoreGraphicsStateClient_Blit2( state->client, &src, &p2, &p1, 1 );
     }
     else
#endif
     {
          /* Scale window to the screen clipped by the region being updated. */
          CoreGraphicsStateClient_StretchBlit( state->client, &src, &dst, 1 );
     }

     /* Restore clipping region. */
     dfb_state_set_clip( state, &old_clip );
}
Beispiel #13
0
void sawman_draw_cursor    ( CoreWindowStack *stack,
                             CardState       *state,
                             CoreSurface     *surface,
                             DFBRegion       *region,
                             int              x,
                             int              y )
{
     DFBRectangle            src;
     DFBRectangle            clip;
     DFBSurfaceBlittingFlags flags = DSBLIT_BLEND_ALPHACHANNEL;

     D_ASSERT( stack != NULL );
     D_MAGIC_ASSERT( state, CardState );
     DFB_REGION_ASSERT( region );

     D_ASSUME( stack->cursor.opacity > 0 );

     D_DEBUG_AT( SaWMan_Draw, "%s( %p, %d,%d-%dx%d )\n", __FUNCTION__,
                 stack, DFB_RECTANGLE_VALS_FROM_REGION( region ) );

     /* Initialize source rectangle. */
     src.x = region->x1 - x + stack->cursor.hot.x;
     src.y = region->y1 - y + stack->cursor.hot.y;
     src.w = region->x2 - region->x1 + 1;
     src.h = region->y2 - region->y1 + 1;

     D_DEBUG_AT( SaWMan_Draw, "  -> cursor surface %p\n", stack->cursor.surface );

     /* Initialize source clipping rectangle */
     clip.x = clip.y = 0;
     clip.w = stack->cursor.surface->config.size.w;
     clip.h = stack->cursor.surface->config.size.h;

     /* Intersect rectangles */
     if (!dfb_rectangle_intersect( &src, &clip ))
          return;

     /* Set destination. */
     if (surface) {
          state->destination  = surface;
          state->modified    |= SMF_DESTINATION;
     }

     /* Use global alpha blending. */
     if (stack->cursor.opacity != 0xFF) {
          flags |= DSBLIT_BLEND_COLORALPHA;

          if (stack->cursor.surface->config.caps & DSCAPS_PREMULTIPLIED) {
               /* Need to premultiply source with Ac? */
               flags |= DSBLIT_SRC_PREMULTCOLOR;

               dfb_state_set_src_blend( state, DSBF_ONE );
          }
          else
               dfb_state_set_src_blend( state, DSBF_SRCALPHA );

          /* Set opacity as blending factor. */
          if (state->color.a != stack->cursor.opacity) {
               state->color.a   = stack->cursor.opacity;
               state->modified |= SMF_COLOR;
          }
     }

     /* Different compositing methods depending on destination format. */
     if (flags & DSBLIT_BLEND_ALPHACHANNEL) {
          if (DFB_PIXELFORMAT_HAS_ALPHA( state->destination->config.format )) {
               /*
                * Always use compliant Porter/Duff SRC_OVER,
                * if the destination has an alpha channel.
                *
                * Cd = destination color  (non-premultiplied)
                * Ad = destination alpha
                *
                * Cs = source color       (non-premultiplied)
                * As = source alpha
                *
                * Ac = color alpha
                *
                * cd = Cd * Ad            (premultiply destination)
                * cs = Cs * As            (premultiply source)
                *
                * The full equation to calculate resulting color and alpha (premultiplied):
                *
                * cx = cd * (1-As*Ac) + cs * Ac
                * ax = Ad * (1-As*Ac) + As * Ac
                */
               dfb_state_set_src_blend( state, DSBF_ONE );

               /* Need to premultiply source with As*Ac or only with Ac? */
               if (! (stack->cursor.surface->config.caps & DSCAPS_PREMULTIPLIED))
                    flags |= DSBLIT_SRC_PREMULTIPLY;
               else if (flags & DSBLIT_BLEND_COLORALPHA)
                    flags |= DSBLIT_SRC_PREMULTCOLOR;

               /* Need to premultiply/demultiply destination? */
//               if (! (state->destination->caps & DSCAPS_PREMULTIPLIED))
//                    flags |= DSBLIT_DST_PREMULTIPLY | DSBLIT_DEMULTIPLY;
          }
          else {
               /*
                * We can avoid DSBLIT_SRC_PREMULTIPLY for destinations without an alpha channel
                * by using another blending function, which is more likely that it's accelerated
                * than premultiplication at this point in time.
                *
                * This way the resulting alpha (ax) doesn't comply with SRC_OVER,
                * but as the destination doesn't have an alpha channel it's no problem.
                *
                * As the destination's alpha value is always 1.0 there's no need for
                * premultiplication. The resulting alpha value will also be 1.0 without
                * exceptions, therefore no need for demultiplication.
                *
                * cx = Cd * (1-As*Ac) + Cs*As * Ac  (still same effect as above)
                * ax = Ad * (1-As*Ac) + As*As * Ac  (wrong, but discarded anyways)
                */
               if (stack->cursor.surface->config.caps & DSCAPS_PREMULTIPLIED) {
                    /* Need to premultiply source with Ac? */
                    if (flags & DSBLIT_BLEND_COLORALPHA)
                         flags |= DSBLIT_SRC_PREMULTCOLOR;

                    dfb_state_set_src_blend( state, DSBF_ONE );
               }
               else
                    dfb_state_set_src_blend( state, DSBF_SRCALPHA );
          }
     }

     /* Set blitting flags. */
     dfb_state_set_blitting_flags( state, flags );

     /* Set blitting source. */
     state->source    = stack->cursor.surface;
     state->from_eye  = DSSE_LEFT;
     state->modified |= SMF_SOURCE | SMF_FROM;

     /* Set clipping region. */
     dfb_state_set_clip( state, region );

     /* Blit from the window to the region being updated. */
     DFBPoint point = {
          region->x1, region->y1
     };
     D_DEBUG_AT( SaWMan_Draw, "  -> client %p\n", state->client );
     CoreGraphicsStateClient_Blit( state->client, &src, &point, 1 );

     /* Reset blitting source. */
     state->source    = NULL;
     state->modified |= SMF_SOURCE;

     /* Reset destination. */
     if (surface) {
          state->destination  = NULL;
          state->modified    |= SMF_DESTINATION;
     }
}