예제 #1
0
DFBResult dfb_surfacemanager_allocate( SurfaceManager *manager,
                                       SurfaceBuffer  *buffer )
{
     int pitch;
     int length;
     Chunk *c;

     Chunk *best_free = NULL;
     Chunk *best_occupied = NULL;

     CoreSurface *surface = buffer->surface;

     D_MAGIC_ASSERT( manager, SurfaceManager );

     if (!manager->length || manager->suspended)
          return DFB_NOVIDEOMEMORY;

     /* calculate the required length depending on limitations */
     pitch = MAX( surface->width, surface->min_width );

     if (pitch < manager->max_power_of_two_pixelpitch &&
         surface->height < manager->max_power_of_two_height)
          pitch = 1 << direct_log2( pitch );

     if (manager->pixelpitch_align > 1) {
          pitch += manager->pixelpitch_align - 1;
          pitch -= pitch % manager->pixelpitch_align;
     }

     pitch = DFB_BYTES_PER_LINE( buffer->format, pitch );

     if (pitch < manager->max_power_of_two_bytepitch &&
         surface->height < manager->max_power_of_two_height)
          pitch = 1 << direct_log2( pitch );

     if (manager->bytepitch_align > 1) {
          pitch += manager->bytepitch_align - 1;
          pitch -= pitch % manager->bytepitch_align;
     }

     length = DFB_PLANE_MULTIPLY( buffer->format,
                                  MAX( surface->height, surface->min_height ) * pitch );

     if (manager->byteoffset_align > 1) {
          length += manager->byteoffset_align - 1;
          length -= length % manager->byteoffset_align;
     }

     /* Do a pre check before iterating through all chunks. */
     if (length > manager->available - manager->heap_offset)
          return DFB_NOVIDEOMEMORY;

     buffer->video.pitch = pitch;

     /* examine chunks */
     c = manager->chunks;
     while (c) {
          if (c->length >= length) {
               if (c->buffer) {
                    c->tolerations++;
                    if (c->tolerations > 0xff)
                         c->tolerations = 0xff;

                    if (!c->buffer->video.locked              &&
                        c->buffer->policy <= buffer->policy   &&
                        c->buffer->policy != CSP_VIDEOONLY    &&

                        ((buffer->policy > c->buffer->policy) ||
                         (c->tolerations > manager->min_toleration/8 + 2)))
                    {
                         /* found a nice place to chill */
                         if (!best_occupied  ||
                              best_occupied->length > c->length  ||
                              best_occupied->tolerations < c->tolerations)
                              /* first found or better one? */
                              best_occupied = c;
                    }
               }
               else {
                    /* found a nice place to chill */
                    if (!best_free  ||  best_free->length > c->length)
                         /* first found or better one? */
                         best_free = c;
               }
          }

          c = c->next;
     }

     /* if we found a place */
     if (best_free) {
          occupy_chunk( manager, best_free, buffer, length );

          return DFB_OK;
     }

     if (best_occupied) {
          CoreSurface *kicked = best_occupied->buffer->surface;

          D_DEBUG_AT( Core_SM, "Kicking out buffer at %d (%d) with tolerations %d...\n",
                      best_occupied->offset,
                      best_occupied->length, best_occupied->tolerations );

          dfb_surfacemanager_assure_system( manager, best_occupied->buffer );

          best_occupied->buffer->video.health = CSH_INVALID;
          dfb_surface_notify_listeners( kicked, CSNF_VIDEO );

          best_occupied = free_chunk( manager, best_occupied );

          dfb_gfxcard_sync();


          occupy_chunk( manager, best_occupied, buffer, length );

          return DFB_OK;
     }


     D_DEBUG_AT( Core_SM, "Couldn't allocate enough heap space for video memory surface!\n" );

     /* no luck */
     return DFB_NOVIDEOMEMORY;
}
예제 #2
0
void mach64gt_set_source_scale( Mach64DriverData *mdrv,
                                Mach64DeviceData *mdev,
                                CardState        *state )
{
     volatile u8 *mmio     = mdrv->mmio_base;
     CoreSurface   *source = state->source;
     unsigned int   offset = state->src.offset;
     unsigned int   pitch  = state->src.pitch;
     int            height = source->config.size.h;

     if (MACH64_IS_VALID( m_source_scale ))
          return;

     mdev->pix_width &= ~SCALE_PIX_WIDTH;
     switch (source->config.format) {
          case DSPF_RGB332:
               mdev->pix_width |= SCALE_PIX_WIDTH_RGB332;
               break;
          case DSPF_RGB555:
          case DSPF_ARGB1555:
               mdev->pix_width |= SCALE_PIX_WIDTH_ARGB1555;
               break;
          case DSPF_RGB444:
          case DSPF_ARGB4444:
               mdev->pix_width |= SCALE_PIX_WIDTH_ARGB4444;
               break;
          case DSPF_RGB16:
               mdev->pix_width |= SCALE_PIX_WIDTH_RGB565;
               break;
          case DSPF_RGB32:
          case DSPF_ARGB:
               mdev->pix_width |= SCALE_PIX_WIDTH_ARGB8888;
               break;
          default:
               D_BUG( "unexpected pixelformat!" );
               return;
     }

     mdev->blit_blend &= ~SCALE_PIX_EXPAND;
     if (DFB_COLOR_BITS_PER_PIXEL( source->config.format ) < 24)
          mdev->blit_blend |= SCALE_PIX_EXPAND;

     mdev->field = source->field;
     if (mdev->blit_deinterlace) {
          if (mdev->field) {
               if (source->config.caps & DSCAPS_SEPARATED) {
                    offset += height/2 * pitch;
               } else {
                    offset += pitch;
                    pitch  *= 2;
               }
          }
          height /= 2;
     }

     mdev->source = source;

     mdev->scale_offset = offset;
     mdev->scale_pitch  = pitch;

     mdev->tex_offset = offset;
     mdev->tex_pitch  = direct_log2( pitch / DFB_BYTES_PER_PIXEL( source->config.format ) );
     mdev->tex_height = direct_log2( height );
     mdev->tex_size   = MAX( mdev->tex_pitch, mdev->tex_height );

     mach64_waitfifo( mdrv, mdev, 1 );
     mach64_out32( mmio, TEX_SIZE_PITCH, (mdev->tex_pitch  << 0) |
                                         (mdev->tex_size   << 4) |
                                         (mdev->tex_height << 8) );

     if (mdev->chip >= CHIP_3D_RAGE_PRO) {
          mach64_waitfifo( mdrv, mdev, 1 );
          mach64_out32( mmio, TEX_CNTL, TEX_CACHE_FLUSH );
     }

     MACH64_VALIDATE( m_source_scale );
}