diff options
author | Uoti Urpala <uau@glyph.nonexistent.invalid> | 2009-02-23 21:00:52 +0200 |
---|---|---|
committer | Uoti Urpala <uau@glyph.nonexistent.invalid> | 2009-02-23 21:00:52 +0200 |
commit | 66f6f9f0768de5b003fc1b0fa9b1ea428466308a (patch) | |
tree | 157b98be78b0cd1e99b3dd51979bc97792d11642 /libvo | |
parent | ebb541c6553af10203b2c2f5bcead6118a44f5be (diff) | |
parent | 30aa2383cadb2f879e02dca9df293c01119a3111 (diff) | |
download | mpv-66f6f9f0768de5b003fc1b0fa9b1ea428466308a.tar.bz2 mpv-66f6f9f0768de5b003fc1b0fa9b1ea428466308a.tar.xz |
Merge svn changes up to r28712
Diffstat (limited to 'libvo')
-rw-r--r-- | libvo/vo_vdpau.c | 197 |
1 files changed, 192 insertions, 5 deletions
diff --git a/libvo/vo_vdpau.c b/libvo/vo_vdpau.c index 738fc64055..d0f6ac07f4 100644 --- a/libvo/vo_vdpau.c +++ b/libvo/vo_vdpau.c @@ -50,6 +50,9 @@ #include "libavutil/common.h" +#include "libass/ass.h" +#include "libass/ass_mp.h" + static vo_info_t info = { "VDPAU with X11", "vdpau", @@ -78,6 +81,9 @@ LIBVO_EXTERN(vdpau) /* number of palette entries */ #define PALETTE_SIZE 256 +/* Initial maximum number of EOSD surfaces */ +#define EOSD_SURFACES_INITIAL 512 + /* * Global variable declaration - VDPAU specific */ @@ -125,6 +131,11 @@ static VdpPresentationQueueTargetCreateX11 *vdp_presentation_queue_target_ /* output_surfaces[2] is used in composite-picture. */ static VdpOutputSurfaceRenderOutputSurface *vdp_output_surface_render_output_surface; static VdpOutputSurfacePutBitsIndexed *vdp_output_surface_put_bits_indexed; +static VdpOutputSurfaceRenderBitmapSurface *vdp_output_surface_render_bitmap_surface; + +static VdpBitmapSurfaceCreate *vdp_bitmap_surface_create; +static VdpBitmapSurfaceDestroy *vdp_bitmap_surface_destroy; +static VdpBitmapSurfacePutBitsNative *vdp_bitmap_surface_putbits_native; static VdpDecoderCreate *vdp_decoder_create; static VdpDecoderDestroy *vdp_decoder_destroy; @@ -159,6 +170,26 @@ static unsigned char *index_data; static int index_data_size; static uint32_t palette[PALETTE_SIZE]; +// EOSD +// Pool of surfaces +struct { + VdpBitmapSurface surface; + int w; + int h; + char in_use; +} *eosd_surfaces; + +// List of surfaces to be rendered +struct { + VdpBitmapSurface surface; + VdpRect source; + VdpRect dest; + VdpColor color; +} *eosd_targets; + +static int eosd_render_count; +static int eosd_surface_count; + /* * X11 specific */ @@ -286,6 +317,12 @@ static int win_x11_init_vdpau_procs(void) {VDP_FUNC_ID_DECODER_CREATE, &vdp_decoder_create}, {VDP_FUNC_ID_DECODER_RENDER, &vdp_decoder_render}, {VDP_FUNC_ID_DECODER_DESTROY, &vdp_decoder_destroy}, + {VDP_FUNC_ID_BITMAP_SURFACE_CREATE, &vdp_bitmap_surface_create}, + {VDP_FUNC_ID_BITMAP_SURFACE_DESTROY, &vdp_bitmap_surface_destroy}, + {VDP_FUNC_ID_BITMAP_SURFACE_PUT_BITS_NATIVE, + &vdp_bitmap_surface_putbits_native}, + {VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_BITMAP_SURFACE, + &vdp_output_surface_render_bitmap_surface}, {0, NULL} }; @@ -330,9 +367,9 @@ static int create_vdp_mixer(VdpChromaType vdp_chroma_type) { int feature_count = 0; VdpVideoMixerFeature features[MAX_NUM_FEATURES]; VdpBool feature_enables[MAX_NUM_FEATURES]; - static const denoise_attrib[] = {VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL}; + static const VdpVideoMixerAttribute denoise_attrib[] = {VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL}; const void * const denoise_value[] = {&denoise}; - static const sharpen_attrib[] = {VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL}; + static const VdpVideoMixerAttribute sharpen_attrib[] = {VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL}; const void * const sharpen_value[] = {&sharpen}; static const VdpVideoMixerParameter parameters[VDP_NUM_MIXER_PARAMETER] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, @@ -390,9 +427,10 @@ static void free_video_specific(void) { surface_render[i].surface = VDP_INVALID_HANDLE; } - if (video_mixer != VDP_INVALID_HANDLE) + if (video_mixer != VDP_INVALID_HANDLE) { vdp_st = vdp_video_mixer_destroy(video_mixer); - CHECK_ST_WARNING("Error when calling vdp_video_mixer_destroy") + CHECK_ST_WARNING("Error when calling vdp_video_mixer_destroy") + } video_mixer = VDP_INVALID_HANDLE; } @@ -563,10 +601,125 @@ static void draw_osd_I8A8(int x0,int y0, int w,int h, unsigned char *src, CHECK_ST_WARNING("Error when calling vdp_output_surface_render_output_surface") } +static void draw_eosd(void) { + VdpStatus vdp_st; + VdpOutputSurface output_surface = output_surfaces[surface_num]; + VdpOutputSurfaceRenderBlendState blend_state; + int i; + + blend_state.struct_version = VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION; + blend_state.blend_factor_source_color = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA; + blend_state.blend_factor_source_alpha = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE; + blend_state.blend_factor_destination_color = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + blend_state.blend_factor_destination_alpha = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA; + blend_state.blend_equation_color = VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD; + blend_state.blend_equation_alpha = VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD; + + for (i=0; i<eosd_render_count; i++) { + vdp_st = vdp_output_surface_render_bitmap_surface( + output_surface, &eosd_targets[i].dest, + eosd_targets[i].surface, &eosd_targets[i].source, + &eosd_targets[i].color, &blend_state, + VDP_OUTPUT_SURFACE_RENDER_ROTATE_0); + CHECK_ST_WARNING("EOSD: Error when rendering") + } +} + +static void generate_eosd(mp_eosd_images_t *imgs) { + VdpStatus vdp_st; + VdpRect destRect; + int j, found; + ass_image_t *img = imgs->imgs; + ass_image_t *i; + + // Nothing changed, no need to redraw + if (imgs->changed == 0) + return; + eosd_render_count = 0; + // There's nothing to render! + if (!img) + return; + + if (imgs->changed == 1) + goto eosd_skip_upload; + + for (j=0; j<eosd_surface_count; j++) + eosd_surfaces[j].in_use = 0; + + for (i = img; i; i = i->next) { + // Try to reuse a suitable surface + found = -1; + for (j=0; j<eosd_surface_count; j++) { + if (eosd_surfaces[j].surface != VDP_INVALID_HANDLE && !eosd_surfaces[j].in_use && + eosd_surfaces[j].w >= i->w && eosd_surfaces[j].h >= i->h) { + found = j; + break; + } + } + // None found, allocate a new surface + if (found < 0) { + for (j=0; j<eosd_surface_count; j++) { + if (!eosd_surfaces[j].in_use) { + if (eosd_surfaces[j].surface != VDP_INVALID_HANDLE) + vdp_bitmap_surface_destroy(eosd_surfaces[j].surface); + found = j; + break; + } + } + // Allocate new space for surface/target arrays + if (found < 0) { + j = found = eosd_surface_count; + eosd_surface_count = eosd_surface_count ? eosd_surface_count*2 : EOSD_SURFACES_INITIAL; + eosd_surfaces = realloc(eosd_surfaces, eosd_surface_count * sizeof(*eosd_surfaces)); + eosd_targets = realloc(eosd_targets, eosd_surface_count * sizeof(*eosd_targets)); + for(j=found; j<eosd_surface_count; j++) { + eosd_surfaces[j].surface = VDP_INVALID_HANDLE; + eosd_surfaces[j].in_use = 0; + } + } + vdp_st = vdp_bitmap_surface_create(vdp_device, VDP_RGBA_FORMAT_A8, + i->w, i->h, VDP_TRUE, &eosd_surfaces[found].surface); + CHECK_ST_WARNING("EOSD: error when creating surface") + eosd_surfaces[found].w = i->w; + eosd_surfaces[found].h = i->h; + } + eosd_surfaces[found].in_use = 1; + eosd_targets[eosd_render_count].surface = eosd_surfaces[found].surface; + destRect.x0 = 0; + destRect.y0 = 0; + destRect.x1 = i->w; + destRect.y1 = i->h; + vdp_st = vdp_bitmap_surface_putbits_native(eosd_targets[eosd_render_count].surface, + (const void *) &i->bitmap, &i->stride, &destRect); + CHECK_ST_WARNING("EOSD: putbits failed") + eosd_render_count++; + } + +eosd_skip_upload: + eosd_render_count = 0; + for (i = img; i; i = i->next) { + // Render dest, color, etc. + eosd_targets[eosd_render_count].color.alpha = 1.0 - ((i->color >> 0) & 0xff) / 255.0; + eosd_targets[eosd_render_count].color.blue = ((i->color >> 8) & 0xff) / 255.0; + eosd_targets[eosd_render_count].color.green = ((i->color >> 16) & 0xff) / 255.0; + eosd_targets[eosd_render_count].color.red = ((i->color >> 24) & 0xff) / 255.0; + eosd_targets[eosd_render_count].dest.x0 = i->dst_x; + eosd_targets[eosd_render_count].dest.y0 = i->dst_y; + eosd_targets[eosd_render_count].dest.x1 = i->w + i->dst_x; + eosd_targets[eosd_render_count].dest.y1 = i->h + i->dst_y; + eosd_targets[eosd_render_count].source.x0 = 0; + eosd_targets[eosd_render_count].source.y0 = 0; + eosd_targets[eosd_render_count].source.x1 = i->w; + eosd_targets[eosd_render_count].source.y1 = i->h; + eosd_render_count++; + } +} + static void draw_osd(void) { mp_msg(MSGT_VO, MSGL_DBG2, "DRAW_OSD\n"); + draw_eosd(); vo_draw_text_ext(vo_dwidth, vo_dheight, border_x, border_y, border_x, border_y, vid_width, vid_height, draw_osd_I8A8); } @@ -695,7 +848,7 @@ static uint32_t get_image(mp_image_t *mpi) static int query_format(uint32_t format) { - int default_flags = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_OSD; + int default_flags = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_OSD | VFCAP_EOSD | VFCAP_EOSD_UNSCALED; switch (format) { case IMGFMT_YV12: return default_flags | VOCAP_NOSLICES; @@ -728,6 +881,14 @@ static void DestroyVdpauObjects(void) CHECK_ST_WARNING("Error when calling vdp_output_surface_destroy") } + for (i = 0; i<eosd_surface_count; i++) { + if (eosd_surfaces[i].surface != VDP_INVALID_HANDLE) { + vdp_st = vdp_bitmap_surface_destroy(eosd_surfaces[i].surface); + CHECK_ST_WARNING("Error when calling vdp_bitmap_surface_destroy") + } + eosd_surfaces[i].surface = VDP_INVALID_HANDLE; + } + vdp_st = vdp_device_destroy(vdp_device); CHECK_ST_WARNING("Error when calling vdp_device_destroy") } @@ -744,6 +905,11 @@ static void uninit(void) free(index_data); index_data = NULL; + free(eosd_surfaces); + eosd_surfaces = NULL; + free(eosd_targets); + eosd_targets = NULL; + #ifdef CONFIG_XF86VM vo_vm_close(); #endif @@ -821,6 +987,10 @@ static int preinit(const char *arg) index_data = NULL; index_data_size = 0; + eosd_surface_count = eosd_render_count = 0; + eosd_surfaces = NULL; + eosd_targets = NULL; + return 0; } @@ -867,6 +1037,23 @@ static int control(uint32_t request, void *data) case VOCTRL_UPDATE_SCREENINFO: update_xinerama_info(); return VO_TRUE; + case VOCTRL_DRAW_EOSD: + if (!data) + return VO_FALSE; + generate_eosd(data); + return VO_TRUE; + case VOCTRL_GET_EOSD_RES: { + mp_eosd_res_t *r = data; + r->mt = r->mb = r->ml = r->mr = 0; + if (vo_fs) { + r->w = vo_screenwidth; + r->h = vo_screenheight; + r->ml = r->mr = border_x; + r->mt = r->mb = border_y; + } else + r->w = vo_dwidth; r->h = vo_dheight; + return VO_TRUE; + } } return VO_NOTIMPL; } |