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