Ticket #1801: mplayer_vdpau-surface.2.diff

File mplayer_vdpau-surface.2.diff, 10.1 KB (added by h.mth@…, 16 years ago)

generate only a few vdpau bitmap surfaces

  • libvo/vo_vdpau.c

    old new  
    7979/* number of palette entries */
    8080#define PALETTE_SIZE 256
    8181
    82 /* Initial maximum number of EOSD surfaces */
    83 #define EOSD_SURFACES_INITIAL 512
     82/* Initial maximum number of EOSD surfaces - this should already be more than enough */
     83#define EOSD_SURFACES_INITIAL 16
     84
     85/* Maximum size of vdpau bitmap surface */
     86#define VDPAU_BITMAP_SURFACE_MAXSIZE 8192
    8487
    8588/*
    8689 * Global variable declaration - VDPAU specific
     
    188191// Pool of surfaces
    189192struct {
    190193    VdpBitmapSurface surface;
    191     int w;
    192     int h;
    193     char in_use;
     194    unsigned int w;
     195    unsigned int h;
     196    unsigned short in_use;
    194197} *eosd_surfaces;
    195198
    196 // List of surfaces to be rendered
     199// List of glyphs to be rendered
    197200struct {
    198201    VdpBitmapSurface surface;
    199202    VdpRect source;
     
    201204    VdpColor color;
    202205} *eosd_targets;
    203206
     207// counters
    204208static int eosd_render_count;
    205209static int eosd_surface_count;
    206210
     211// sizes
     212static int eosd_render_size;
     213
    207214// Video equalizer
    208215static VdpProcamp procamp;
    209216
     
    854861    }
    855862}
    856863
     864static int eosd_invalidGlyph(ASS_Image* i)
     865{
     866    // Invalid bitmap sizes
     867    if (i->w < 0 || i->h < 0 || i->stride < 0
     868        || i->w > VDPAU_BITMAP_SURFACE_MAXSIZE
     869        || i->h > VDPAU_BITMAP_SURFACE_MAXSIZE)
     870       return -1;
     871    return 0;
     872}
     873
    857874static void generate_eosd(EOSD_ImageList *imgs)
    858875{
    859876    VdpStatus vdp_st;
    860     VdpRect destRect;
    861     int j, found;
     877    VdpRect vdp_surface_rect;
     878    int j, found, start_x;
    862879    ASS_Image *img = imgs->imgs;
    863880    ASS_Image *i;
     881    ASS_Image *i_prev;
    864882
    865883    // Nothing changed, no need to redraw
    866884    if (imgs->changed == 0)
    867885        return;
     886
     887    // Hide eosd again ...
    868888    eosd_render_count = 0;
     889
    869890    // There's nothing to render!
    870891    if (!img)
    871892        return;
     
    873894    if (imgs->changed == 1)
    874895        goto eosd_skip_upload;
    875896
    876     for (j = 0; j < eosd_surface_count; j++)
     897    // OPTIONAL: No need to try to reuse - simplification
     898    for (j = 0; j < eosd_surface_count; j++) {
    877899        eosd_surfaces[j].in_use = 0;
     900        //if (eosd_surfaces[j].surface != VDP_INVALID_HANDLE) {
     901        //    vdp_bitmap_surface_destroy(eosd_surfaces[j].surface);
     902        //    CHECK_ST_WARNING("Error when calling vdp_bitmap_surface_destroy")
     903        //    eosd_surfaces[j].surface = VDP_INVALID_HANDLE;
     904        //}
     905    }
     906
     907    // Initialize handling of surfaces
     908    found = 0;
     909    vdp_surface_rect.x1 = 0;
     910    vdp_surface_rect.y1 = 0;
    878911
    879912    for (i = img; i; i = i->next) {
    880         // Try to reuse a suitable surface
    881         found = -1;
    882         for (j = 0; j < eosd_surface_count; j++) {
    883             if (eosd_surfaces[j].surface != VDP_INVALID_HANDLE && !eosd_surfaces[j].in_use &&
    884                 eosd_surfaces[j].w >= i->w && eosd_surfaces[j].h >= i->h) {
    885                 found = j;
    886                 break;
    887             }
     913        if (eosd_invalidGlyph (i))
     914            continue;
     915
     916        // Create bitmap surface and restart with current glyph
     917        if (vdp_surface_rect.x1 + i->w > VDPAU_BITMAP_SURFACE_MAXSIZE) {
     918            i = i_prev;
     919
     920        // Collect glyphs for one surface
     921        } else {
     922            // Get render count
     923            eosd_render_count++;
     924
     925            i_prev = i;
     926            vdp_surface_rect.x1 += i->w;
     927
     928            if (i->h > vdp_surface_rect.y1)
     929                vdp_surface_rect.y1 = i->h;
     930            if (i->next)
     931                continue;
    888932        }
    889         // None found, allocate a new surface
    890         if (found < 0) {
    891             for (j = 0; j < eosd_surface_count; j++) {
    892                 if (!eosd_surfaces[j].in_use) {
    893                     if (eosd_surfaces[j].surface != VDP_INVALID_HANDLE)
    894                         vdp_bitmap_surface_destroy(eosd_surfaces[j].surface);
    895                     found = j;
    896                     break;
    897                 }
     933
     934        // Allocate new space for surface arrays
     935        if (eosd_surface_count <= found) {
     936            j = eosd_surface_count;
     937            eosd_surface_count = eosd_surface_count ? eosd_surface_count*2 : EOSD_SURFACES_INITIAL;
     938            eosd_surfaces = realloc(eosd_surfaces, eosd_surface_count * sizeof(*eosd_surfaces));
     939            for (; j < eosd_surface_count; j++) {
     940                eosd_surfaces[j].surface = VDP_INVALID_HANDLE;
     941                eosd_surfaces[j].in_use = 0;
    898942            }
    899             // Allocate new space for surface/target arrays
    900             if (found < 0) {
    901                 j = found = eosd_surface_count;
    902                 eosd_surface_count = eosd_surface_count ? eosd_surface_count*2 : EOSD_SURFACES_INITIAL;
    903                 eosd_surfaces = realloc(eosd_surfaces, eosd_surface_count * sizeof(*eosd_surfaces));
    904                 eosd_targets  = realloc(eosd_targets,  eosd_surface_count * sizeof(*eosd_targets));
    905                 for (j = found; j < eosd_surface_count; j++) {
    906                     eosd_surfaces[j].surface = VDP_INVALID_HANDLE;
    907                     eosd_surfaces[j].in_use = 0;
    908                 }
     943        }
     944
     945        // OPTIONAL: No need to try to reuse - simplification
     946        if (eosd_surfaces[found].surface == VDP_INVALID_HANDLE ||
     947            eosd_surfaces[found].w < vdp_surface_rect.x1 || eosd_surfaces[found].h < vdp_surface_rect.y1) {
     948            // Destroy surface
     949            if (eosd_surfaces[found].surface != VDP_INVALID_HANDLE) {
     950                vdp_bitmap_surface_destroy(eosd_surfaces[found].surface);
     951                CHECK_ST_WARNING("Error when calling vdp_bitmap_surface_destroy")
     952
     953                // Increase w or h only - relax oscillation
     954                vdp_surface_rect.x1 = (vdp_surface_rect.x1 < eosd_surfaces[found].w) ? eosd_surfaces[found].w : vdp_surface_rect.x1;
     955                vdp_surface_rect.y1 = (vdp_surface_rect.y1 < eosd_surfaces[found].h) ? eosd_surfaces[found].h : vdp_surface_rect.y1;
    909956            }
     957
     958            // Create bigger surface
    910959            vdp_st = vdp_bitmap_surface_create(vdp_device, VDP_RGBA_FORMAT_A8,
    911                 i->w, i->h, VDP_TRUE, &eosd_surfaces[found].surface);
     960                vdp_surface_rect.x1, vdp_surface_rect.y1, VDP_TRUE, &eosd_surfaces[found].surface);
    912961            CHECK_ST_WARNING("EOSD: error when creating surface")
    913             eosd_surfaces[found].w = i->w;
    914             eosd_surfaces[found].h = i->h;
     962            eosd_surfaces[found].w = vdp_surface_rect.x1;
     963            eosd_surfaces[found].h = vdp_surface_rect.y1;
     964
     965            //printf ("surface: n:%d w:%d h:%d c:%d ...\n", found, vdp_surface_rect.x1, vdp_surface_rect.y1, eosd_render_count);
    915966        }
    916         eosd_surfaces[found].in_use = 1;
     967
     968        eosd_surfaces[found].in_use = eosd_render_count;
     969
     970        // Set surface data
     971        vdp_surface_rect.x1 = 0;
     972        vdp_surface_rect.y1 = 0;
     973
     974        // Get surface count
     975        found++;
     976    }
     977
     978    // Allocate new space for target arrays
     979    if (eosd_render_size < eosd_render_count) {
     980        eosd_render_size = eosd_render_count;
     981
     982        eosd_targets = realloc(eosd_targets, eosd_render_count * sizeof(*eosd_targets));
     983    }
     984
     985    start_x = 0;
     986    found = 0;
     987    eosd_render_count = 0;
     988
     989    for (i = img; i; i = i->next) {
     990        if (eosd_invalidGlyph (i))
     991            continue;
     992
     993        if (eosd_render_count == eosd_surfaces[found].in_use) {
     994            found++;
     995            start_x = 0;
     996        }
     997
    917998        eosd_targets[eosd_render_count].surface = eosd_surfaces[found].surface;
    918         destRect.x0 = 0;
    919         destRect.y0 = 0;
    920         destRect.x1 = i->w;
    921         destRect.y1 = i->h;
     999        eosd_targets[eosd_render_count].source.x0 = start_x;
     1000        eosd_targets[eosd_render_count].source.y0 = 0;
     1001        eosd_targets[eosd_render_count].source.x1 = start_x + i->w;
     1002        eosd_targets[eosd_render_count].source.y1 = i->h;
     1003
     1004        //printf ("rect: n:%d w:%d h:%d x:%d y:%d ...\n", found, i->w, i->h, eosd_targets[eosd_render_count].source.x0, eosd_targets[eosd_render_count].source.y0 );
     1005
    9221006        vdp_st = vdp_bitmap_surface_putbits_native(eosd_targets[eosd_render_count].surface,
    923             (const void *) &i->bitmap, &i->stride, &destRect);
     1007            (const void *) &i->bitmap, &i->stride, &eosd_targets[eosd_render_count].source);
    9241008        CHECK_ST_WARNING("EOSD: putbits failed")
     1009
     1010        start_x += i->w;
    9251011        eosd_render_count++;
    9261012    }
    9271013
    9281014eosd_skip_upload:
    9291015    eosd_render_count = 0;
    9301016    for (i = img; i; i = i->next) {
    931         // Render dest, color, etc.
     1017        if (eosd_invalidGlyph (i))
     1018            continue;
     1019
     1020        // Render dest and color only
    9321021        eosd_targets[eosd_render_count].color.alpha = 1.0 - ((i->color >>  0) & 0xff) / 255.0;
    9331022        eosd_targets[eosd_render_count].color.blue  =       ((i->color >>  8) & 0xff) / 255.0;
    9341023        eosd_targets[eosd_render_count].color.green =       ((i->color >> 16) & 0xff) / 255.0;
    9351024        eosd_targets[eosd_render_count].color.red   =       ((i->color >> 24) & 0xff) / 255.0;
    936         eosd_targets[eosd_render_count].dest.x0     =        i->dst_x;
    937         eosd_targets[eosd_render_count].dest.y0     =        i->dst_y;
    938         eosd_targets[eosd_render_count].dest.x1     = i->w + i->dst_x;
    939         eosd_targets[eosd_render_count].dest.y1     = i->h + i->dst_y;
    940         eosd_targets[eosd_render_count].source.x0   = 0;
    941         eosd_targets[eosd_render_count].source.y0   = 0;
    942         eosd_targets[eosd_render_count].source.x1   = i->w;
    943         eosd_targets[eosd_render_count].source.y1   = i->h;
     1025
     1026        //printf ("color: r:%f g:%f b:%f a:%f ...\n", eosd_targets[eosd_render_count].color.red, eosd_targets[eosd_render_count].color.green, eosd_targets[eosd_render_count].color.blue, eosd_targets[eosd_render_count].color.alpha);
     1027
     1028        eosd_targets[eosd_render_count].dest.x0     = i->dst_x;
     1029        eosd_targets[eosd_render_count].dest.y0     = i->dst_y;
     1030        eosd_targets[eosd_render_count].dest.x1     = i->dst_x + i->w;
     1031        eosd_targets[eosd_render_count].dest.y1     = i->dst_y + i->h;
    9441032        eosd_render_count++;
    9451033    }
    9461034}
     
    12691357    index_data_size = 0;
    12701358
    12711359    eosd_surface_count = eosd_render_count = 0;
     1360    eosd_render_size = 0;
    12721361    eosd_surfaces = NULL;
    12731362    eosd_targets  = NULL;
    12741363