diff options
Diffstat (limited to 'libvo')
-rw-r--r-- | libvo/cocoa_common.h | 3 | ||||
-rw-r--r-- | libvo/cocoa_common.m | 47 | ||||
-rw-r--r-- | libvo/d3d_shader_yuv.h | 142 | ||||
-rw-r--r-- | libvo/d3d_shader_yuv.hlsl | 44 | ||||
-rw-r--r-- | libvo/d3d_shader_yuv_2ch.h | 170 | ||||
-rw-r--r-- | libvo/eosd_packer.c | 254 | ||||
-rw-r--r-- | libvo/eosd_packer.h | 71 | ||||
-rw-r--r-- | libvo/filter_kernels.c | 279 | ||||
-rw-r--r-- | libvo/filter_kernels.h | 45 | ||||
-rw-r--r-- | libvo/gl_common.c | 845 | ||||
-rw-r--r-- | libvo/gl_common.h | 342 | ||||
-rw-r--r-- | libvo/gl_header_fixes.h | 231 | ||||
-rw-r--r-- | libvo/mga_template.c | 2 | ||||
-rw-r--r-- | libvo/video_out.c | 16 | ||||
-rw-r--r-- | libvo/vo_direct3d.c | 2137 | ||||
-rw-r--r-- | libvo/vo_directfb2.c | 14 | ||||
-rw-r--r-- | libvo/vo_directx.c | 1742 | ||||
-rw-r--r-- | libvo/vo_gl.c | 326 | ||||
-rw-r--r-- | libvo/vo_gl3.c | 2418 | ||||
-rw-r--r-- | libvo/vo_gl3_shaders.glsl | 316 | ||||
-rw-r--r-- | libvo/vo_svga.c | 4 | ||||
-rw-r--r-- | libvo/vo_vdpau.c | 255 | ||||
-rw-r--r-- | libvo/w32_common.c | 355 | ||||
-rw-r--r-- | libvo/x11_common.c | 3 |
24 files changed, 7702 insertions, 2359 deletions
diff --git a/libvo/cocoa_common.h b/libvo/cocoa_common.h index 16f9a2f1f9..d47ac51500 100644 --- a/libvo/cocoa_common.h +++ b/libvo/cocoa_common.h @@ -29,7 +29,8 @@ void vo_cocoa_update_xinerama_info(struct vo *vo); int vo_cocoa_change_attributes(struct vo *vo); int vo_cocoa_create_window(struct vo *vo, uint32_t d_width, - uint32_t d_height, uint32_t flags); + uint32_t d_height, uint32_t flags, + int gl3profile); void vo_cocoa_swap_buffers(void); int vo_cocoa_check_events(struct vo *vo); diff --git a/libvo/cocoa_common.m b/libvo/cocoa_common.m index f5ad7a0943..e8ef278b1e 100644 --- a/libvo/cocoa_common.m +++ b/libvo/cocoa_common.m @@ -20,7 +20,7 @@ #import <Cocoa/Cocoa.h> #import <OpenGL/OpenGL.h> #import <QuartzCore/QuartzCore.h> -#import <CoreServices/CoreServices.h> // for CGDisplayHideCursor +#import <CoreServices/CoreServices.h> // for CGDisplayHideCursor and Gestalt #include "cocoa_common.h" #include "options.h" @@ -35,6 +35,18 @@ #include "osx_common.h" #include "mp_msg.h" +#ifndef NSOpenGLPFAOpenGLProfile +#define NSOpenGLPFAOpenGLProfile 99 +#endif + +#ifndef NSOpenGLProfileVersionLegacy +#define NSOpenGLProfileVersionLegacy 0x1000 +#endif + +#ifndef NSOpenGLProfileVersion3_2Core +#define NSOpenGLProfileVersion3_2Core 0x3200 +#endif + #define NSLeftAlternateKeyMask (0x000020 | NSAlternateKeyMask) #define NSRightAlternateKeyMask (0x000040 | NSAlternateKeyMask) @@ -94,6 +106,8 @@ void resize_window(struct vo *vo); void vo_cocoa_display_cursor(int requested_state); void create_menu(void); +bool is_lion_or_better(void); + struct vo_cocoa_state *vo_cocoa_init_state(void) { struct vo_cocoa_state *s = talloc_ptrtype(NULL, s); @@ -192,7 +206,8 @@ void vo_cocoa_ontop(struct vo *vo) } int vo_cocoa_create_window(struct vo *vo, uint32_t d_width, - uint32_t d_height, uint32_t flags) + uint32_t d_height, uint32_t flags, + int gl3profile) { struct MPOpts *opts = vo->opts; if (s->current_video_size.width > 0 || s->current_video_size.height > 0) @@ -206,13 +221,18 @@ int vo_cocoa_create_window(struct vo *vo, uint32_t d_width, GLMPlayerOpenGLView *glView = [[GLMPlayerOpenGLView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)]; - NSOpenGLPixelFormatAttribute attrs[] = { - NSOpenGLPFADoubleBuffer, // double buffered - NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)16, // 16 bit depth buffer - (NSOpenGLPixelFormatAttribute)0 - }; + int i = 0; + NSOpenGLPixelFormatAttribute attr[32]; + if (is_lion_or_better()) { + attr[i++] = NSOpenGLPFAOpenGLProfile; + attr[i++] = (gl3profile ? NSOpenGLProfileVersion3_2Core : NSOpenGLProfileVersionLegacy); + } + attr[i++] = NSOpenGLPFADoubleBuffer; // double buffered + attr[i++] = NSOpenGLPFADepthSize; + attr[i++] = (NSOpenGLPixelFormatAttribute)16; // 16 bit depth buffer + attr[i] = (NSOpenGLPixelFormatAttribute)0; - NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]; + NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr]; s->glContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil]; create_menu(); @@ -368,6 +388,17 @@ void create_menu() [menuItem release]; } +bool is_lion_or_better(void) +{ + SInt32 major, minor; + Gestalt(gestaltSystemVersionMajor, &major); + Gestalt(gestaltSystemVersionMinor, &minor); + if(major >= 10 && minor >= 7) + return YES; + else + return NO; +} + @implementation GLMPlayerWindow - (void) windowDidResize:(NSNotification *) notification diff --git a/libvo/d3d_shader_yuv.h b/libvo/d3d_shader_yuv.h new file mode 100644 index 0000000000..49ef753b4c --- /dev/null +++ b/libvo/d3d_shader_yuv.h @@ -0,0 +1,142 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022 +// +// fxc /Tps_2_0 /Fhz:\tmp\mplayer\libvo\d3d_shader_yuv.h +// z:\tmp\mplayer\libvo\d3d_shader_yuv.hlsl /Vnd3d_shader_yuv +// +// +// Parameters: +// +// float4x4 colormatrix; +// sampler2D tex0; +// sampler2D tex1; +// sampler2D tex2; +// +// +// Registers: +// +// Name Reg Size +// ------------ ----- ---- +// colormatrix c0 4 +// tex0 s0 1 +// tex1 s1 1 +// tex2 s2 1 +// + + ps_2_0 + def c4, 1, 0, 0, 0 + dcl t0.xy + dcl t1.xy + dcl t2.xy + dcl_2d s0 + dcl_2d s1 + dcl_2d s2 + texld r0, t0, s0 + texld r1, t1, s1 + texld r2, t2, s2 + mov r0.y, r1.x + mov r0.z, r2.x + mov r0.w, c4.x + dp4 r1.x, r0, c0 + dp4 r1.y, r0, c1 + dp4 r1.z, r0, c2 + dp4 r1.w, r0, c3 + mov oC0, r1 + +// approximately 11 instruction slots used (3 texture, 8 arithmetic) +#endif + +const BYTE d3d_shader_yuv[] = +{ + 0, 2, 255, 255, 254, 255, + 67, 0, 67, 84, 65, 66, + 28, 0, 0, 0, 215, 0, + 0, 0, 0, 2, 255, 255, + 4, 0, 0, 0, 28, 0, + 0, 0, 0, 1, 0, 0, + 208, 0, 0, 0, 108, 0, + 0, 0, 2, 0, 0, 0, + 4, 0, 2, 0, 120, 0, + 0, 0, 0, 0, 0, 0, + 136, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 2, 0, + 144, 0, 0, 0, 0, 0, + 0, 0, 160, 0, 0, 0, + 3, 0, 1, 0, 1, 0, + 6, 0, 168, 0, 0, 0, + 0, 0, 0, 0, 184, 0, + 0, 0, 3, 0, 2, 0, + 1, 0, 10, 0, 192, 0, + 0, 0, 0, 0, 0, 0, + 99, 111, 108, 111, 114, 109, + 97, 116, 114, 105, 120, 0, + 3, 0, 3, 0, 4, 0, + 4, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 116, 101, + 120, 48, 0, 171, 171, 171, + 4, 0, 12, 0, 1, 0, + 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 116, 101, + 120, 49, 0, 171, 171, 171, + 4, 0, 12, 0, 1, 0, + 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 116, 101, + 120, 50, 0, 171, 171, 171, + 4, 0, 12, 0, 1, 0, + 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 112, 115, + 95, 50, 95, 48, 0, 77, + 105, 99, 114, 111, 115, 111, + 102, 116, 32, 40, 82, 41, + 32, 72, 76, 83, 76, 32, + 83, 104, 97, 100, 101, 114, + 32, 67, 111, 109, 112, 105, + 108, 101, 114, 32, 57, 46, + 50, 55, 46, 57, 53, 50, + 46, 51, 48, 50, 50, 0, + 81, 0, 0, 5, 4, 0, + 15, 160, 0, 0, 128, 63, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 31, 0, 0, 2, 0, 0, + 0, 128, 0, 0, 3, 176, + 31, 0, 0, 2, 0, 0, + 0, 128, 1, 0, 3, 176, + 31, 0, 0, 2, 0, 0, + 0, 128, 2, 0, 3, 176, + 31, 0, 0, 2, 0, 0, + 0, 144, 0, 8, 15, 160, + 31, 0, 0, 2, 0, 0, + 0, 144, 1, 8, 15, 160, + 31, 0, 0, 2, 0, 0, + 0, 144, 2, 8, 15, 160, + 66, 0, 0, 3, 0, 0, + 15, 128, 0, 0, 228, 176, + 0, 8, 228, 160, 66, 0, + 0, 3, 1, 0, 15, 128, + 1, 0, 228, 176, 1, 8, + 228, 160, 66, 0, 0, 3, + 2, 0, 15, 128, 2, 0, + 228, 176, 2, 8, 228, 160, + 1, 0, 0, 2, 0, 0, + 2, 128, 1, 0, 0, 128, + 1, 0, 0, 2, 0, 0, + 4, 128, 2, 0, 0, 128, + 1, 0, 0, 2, 0, 0, + 8, 128, 4, 0, 0, 160, + 9, 0, 0, 3, 1, 0, + 1, 128, 0, 0, 228, 128, + 0, 0, 228, 160, 9, 0, + 0, 3, 1, 0, 2, 128, + 0, 0, 228, 128, 1, 0, + 228, 160, 9, 0, 0, 3, + 1, 0, 4, 128, 0, 0, + 228, 128, 2, 0, 228, 160, + 9, 0, 0, 3, 1, 0, + 8, 128, 0, 0, 228, 128, + 3, 0, 228, 160, 1, 0, + 0, 2, 0, 8, 15, 128, + 1, 0, 228, 128, 255, 255, + 0, 0 +}; diff --git a/libvo/d3d_shader_yuv.hlsl b/libvo/d3d_shader_yuv.hlsl new file mode 100644 index 0000000000..b17e257210 --- /dev/null +++ b/libvo/d3d_shader_yuv.hlsl @@ -0,0 +1,44 @@ +// Compile with: +// fxc.exe /Tps_2_0 /Fhd3d_shader_yuv.h d3d_shader_yuv.hlsl /Vnd3d_shader_yuv +// fxc.exe /Tps_2_0 /Fhd3d_shader_yuv_2ch.h d3d_shader_yuv.hlsl /Vnd3d_shader_yuv_2ch /DUSE_2CH=1 + +// Be careful with this shader. You can't use constant slots, since we don't +// load the shader with D3DX. All uniform variables are mapped to hardcoded +// constant slots. + +sampler2D tex0 : register(s0); +sampler2D tex1 : register(s1); +sampler2D tex2 : register(s2); + +uniform float4x4 colormatrix : register(c0); +uniform float2 depth : register(c5); + +#ifdef USE_2CH + +float1 sample(sampler2D tex, float2 t) +{ + // Sample from A8L8 format as if we sampled a single value from L16. + // We compute the 2 channel values back into one. + return dot(tex2D(tex, t).xw, depth); +} + +#else + +float1 sample(sampler2D tex, float2 t) +{ + return tex2D(tex, t).x; +} + +#endif + +float4 main(float2 t0 : TEXCOORD0, + float2 t1 : TEXCOORD1, + float2 t2 : TEXCOORD2) + : COLOR +{ + float4 c = float4(sample(tex0, t0), + sample(tex1, t1), + sample(tex2, t2), + 1); + return mul(c, colormatrix); +} diff --git a/libvo/d3d_shader_yuv_2ch.h b/libvo/d3d_shader_yuv_2ch.h new file mode 100644 index 0000000000..45dcc73992 --- /dev/null +++ b/libvo/d3d_shader_yuv_2ch.h @@ -0,0 +1,170 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022 +// +// fxc /Tps_2_0 /Fhz:\tmp\mplayer\libvo\d3d_shader_yuv_2ch.h +// z:\tmp\mplayer\libvo\d3d_shader_yuv.hlsl /Vnd3d_shader_yuv_2ch +// /DUSE_2CH=1 +// +// +// Parameters: +// +// float4x4 colormatrix; +// float2 depth; +// sampler2D tex0; +// sampler2D tex1; +// sampler2D tex2; +// +// +// Registers: +// +// Name Reg Size +// ------------ ----- ---- +// colormatrix c0 4 +// depth c5 1 +// tex0 s0 1 +// tex1 s1 1 +// tex2 s2 1 +// + + ps_2_0 + def c4, 1, 0, 0, 0 + dcl t0.xy + dcl t1.xy + dcl t2.xy + dcl_2d s0 + dcl_2d s1 + dcl_2d s2 + texld r0, t0, s0 + texld r1, t1, s1 + texld r2, t2, s2 + mul r0.x, r0.x, c5.x + mad r0.x, r0.w, c5.y, r0.x + mul r1.x, r1.x, c5.x + mad r0.y, r1.w, c5.y, r1.x + mul r1.x, r2.x, c5.x + mad r0.z, r2.w, c5.y, r1.x + mov r0.w, c4.x + dp4 r1.x, r0, c0 + dp4 r1.y, r0, c1 + dp4 r1.z, r0, c2 + dp4 r1.w, r0, c3 + mov oC0, r1 + +// approximately 15 instruction slots used (3 texture, 12 arithmetic) +#endif + +const BYTE d3d_shader_yuv_2ch[] = +{ + 0, 2, 255, 255, 254, 255, + 78, 0, 67, 84, 65, 66, + 28, 0, 0, 0, 3, 1, + 0, 0, 0, 2, 255, 255, + 5, 0, 0, 0, 28, 0, + 0, 0, 0, 1, 0, 0, + 252, 0, 0, 0, 128, 0, + 0, 0, 2, 0, 0, 0, + 4, 0, 2, 0, 140, 0, + 0, 0, 0, 0, 0, 0, + 156, 0, 0, 0, 2, 0, + 5, 0, 1, 0, 22, 0, + 164, 0, 0, 0, 0, 0, + 0, 0, 180, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 2, 0, 188, 0, 0, 0, + 0, 0, 0, 0, 204, 0, + 0, 0, 3, 0, 1, 0, + 1, 0, 6, 0, 212, 0, + 0, 0, 0, 0, 0, 0, + 228, 0, 0, 0, 3, 0, + 2, 0, 1, 0, 10, 0, + 236, 0, 0, 0, 0, 0, + 0, 0, 99, 111, 108, 111, + 114, 109, 97, 116, 114, 105, + 120, 0, 3, 0, 3, 0, + 4, 0, 4, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 100, 101, 112, 116, 104, 0, + 171, 171, 1, 0, 3, 0, + 1, 0, 2, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 116, 101, 120, 48, 0, 171, + 171, 171, 4, 0, 12, 0, + 1, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 116, 101, 120, 49, 0, 171, + 171, 171, 4, 0, 12, 0, + 1, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 116, 101, 120, 50, 0, 171, + 171, 171, 4, 0, 12, 0, + 1, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 112, 115, 95, 50, 95, 48, + 0, 77, 105, 99, 114, 111, + 115, 111, 102, 116, 32, 40, + 82, 41, 32, 72, 76, 83, + 76, 32, 83, 104, 97, 100, + 101, 114, 32, 67, 111, 109, + 112, 105, 108, 101, 114, 32, + 57, 46, 50, 55, 46, 57, + 53, 50, 46, 51, 48, 50, + 50, 0, 81, 0, 0, 5, + 4, 0, 15, 160, 0, 0, + 128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 31, 0, 0, 2, + 0, 0, 0, 128, 0, 0, + 3, 176, 31, 0, 0, 2, + 0, 0, 0, 128, 1, 0, + 3, 176, 31, 0, 0, 2, + 0, 0, 0, 128, 2, 0, + 3, 176, 31, 0, 0, 2, + 0, 0, 0, 144, 0, 8, + 15, 160, 31, 0, 0, 2, + 0, 0, 0, 144, 1, 8, + 15, 160, 31, 0, 0, 2, + 0, 0, 0, 144, 2, 8, + 15, 160, 66, 0, 0, 3, + 0, 0, 15, 128, 0, 0, + 228, 176, 0, 8, 228, 160, + 66, 0, 0, 3, 1, 0, + 15, 128, 1, 0, 228, 176, + 1, 8, 228, 160, 66, 0, + 0, 3, 2, 0, 15, 128, + 2, 0, 228, 176, 2, 8, + 228, 160, 5, 0, 0, 3, + 0, 0, 1, 128, 0, 0, + 0, 128, 5, 0, 0, 160, + 4, 0, 0, 4, 0, 0, + 1, 128, 0, 0, 255, 128, + 5, 0, 85, 160, 0, 0, + 0, 128, 5, 0, 0, 3, + 1, 0, 1, 128, 1, 0, + 0, 128, 5, 0, 0, 160, + 4, 0, 0, 4, 0, 0, + 2, 128, 1, 0, 255, 128, + 5, 0, 85, 160, 1, 0, + 0, 128, 5, 0, 0, 3, + 1, 0, 1, 128, 2, 0, + 0, 128, 5, 0, 0, 160, + 4, 0, 0, 4, 0, 0, + 4, 128, 2, 0, 255, 128, + 5, 0, 85, 160, 1, 0, + 0, 128, 1, 0, 0, 2, + 0, 0, 8, 128, 4, 0, + 0, 160, 9, 0, 0, 3, + 1, 0, 1, 128, 0, 0, + 228, 128, 0, 0, 228, 160, + 9, 0, 0, 3, 1, 0, + 2, 128, 0, 0, 228, 128, + 1, 0, 228, 160, 9, 0, + 0, 3, 1, 0, 4, 128, + 0, 0, 228, 128, 2, 0, + 228, 160, 9, 0, 0, 3, + 1, 0, 8, 128, 0, 0, + 228, 128, 3, 0, 228, 160, + 1, 0, 0, 2, 0, 8, + 15, 128, 1, 0, 228, 128, + 255, 255, 0, 0 +}; diff --git a/libvo/eosd_packer.c b/libvo/eosd_packer.c new file mode 100644 index 0000000000..103648b7c4 --- /dev/null +++ b/libvo/eosd_packer.c @@ -0,0 +1,254 @@ +/* + * Common code for packing EOSD images into larger surfaces. + * + * This file is part of mplayer2. + * + * mplayer2 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mplayer2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with mplayer2; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <libavutil/common.h> +#include "talloc.h" +#include "mp_msg.h" +#include "eosd_packer.h" + +// Initial size of EOSD surface in pixels (x*x) +#define EOSD_SURFACE_INITIAL_SIZE 256 + +// Allocate an eosd_packer, which can be used to layout and cache the list of +// EOSD images contained in a mp_eosd_images_t into a flat surface. +// It can be free'd with talloc_free(). +// Don't forget to call eosd_init() before using it. +struct eosd_packer *eosd_packer_create(void *talloc_ctx) { + return talloc_zero(talloc_ctx, struct eosd_packer); +} + +// Call this when you need to completely reinitialize the EOSD state, e.g. when +// when your EOSD surface was deleted. +// max_width and max_height are the maximum surface sizes that should be +// allowed. +void eosd_packer_reinit(struct eosd_packer *state, uint32_t max_width, + uint32_t max_height) +{ + state->max_surface_width = max_width; + state->max_surface_height = max_height; + state->surface.w = 0; + state->surface.h = 0; + state->targets_count = 0; +} + +#define HEIGHT_SORT_BITS 4 +static int size_index(struct eosd_target *r) +{ + unsigned int h = r->source.y1; + int n = av_log2_16bit(h); + return (n << HEIGHT_SORT_BITS) + + (- 1 - (h << HEIGHT_SORT_BITS >> n) & (1 << HEIGHT_SORT_BITS) - 1); +} + +/* Pack the given rectangles into an area of size w * h. + * The size of each rectangle is read from .source.x1/.source.y1. + * The height of each rectangle must be at least 1 and less than 65536. + * The .source rectangle is then set corresponding to the packed position. + * 'scratch' must point to work memory for num_rects+16 ints. + * Return 0 on success, -1 if the rectangles did not fit in w*h. + * + * The rectangles are placed in rows in order approximately sorted by + * height (the approximate sorting is simpler than a full one would be, + * and allows the algorithm to work in linear time). Additionally, to + * reduce wasted space when there are a few tall rectangles, empty + * lower-right parts of rows are filled recursively when the size of + * rectangles in the row drops past a power-of-two threshold. So if a + * row starts with rectangles of size 3x50, 10x40 and 5x20 then the + * free rectangle with corners (13, 20)-(w, 50) is filled recursively. + */ +static int pack_rectangles(struct eosd_target *rects, int num_rects, + int w, int h, int *scratch) +{ + int bins[16 << HEIGHT_SORT_BITS]; + int sizes[16 << HEIGHT_SORT_BITS] = {}; + for (int i = 0; i < num_rects; i++) + sizes[size_index(rects + i)]++; + int idx = 0; + for (int i = 0; i < 16 << HEIGHT_SORT_BITS; i += 1 << HEIGHT_SORT_BITS) { + for (int j = 0; j < 1 << HEIGHT_SORT_BITS; j++) { + bins[i + j] = idx; + idx += sizes[i + j]; + } + scratch[idx++] = -1; + } + for (int i = 0; i < num_rects; i++) + scratch[bins[size_index(rects + i)]++] = i; + for (int i = 0; i < 16; i++) + bins[i] = bins[i << HEIGHT_SORT_BITS] - sizes[i << HEIGHT_SORT_BITS]; + struct { + int size, x, bottom; + } stack[16] = {{15, 0, h}}, s = {}; + int stackpos = 1; + int y; + while (stackpos) { + y = s.bottom; + s = stack[--stackpos]; + s.size++; + while (s.size--) { + int maxy = -1; + int obj; + while ((obj = scratch[bins[s.size]]) >= 0) { + int bottom = y + rects[obj].source.y1; + if (bottom > s.bottom) + break; + int right = s.x + rects[obj].source.x1; + if (right > w) + break; + bins[s.size]++; + rects[obj].source.x0 = s.x; + rects[obj].source.x1 += s.x; + rects[obj].source.y0 = y; + rects[obj].source.y1 += y; + num_rects--; + if (maxy <= 0) + stack[stackpos++] = s; + s.x = right; + maxy = FFMAX(maxy, bottom); + } + if (maxy > 0) + s.bottom = maxy; + } + } + return num_rects ? -1 : 0; +} + +// padding to reduce interpolation artifacts when doing scaling & filtering +#define EOSD_PADDING 0 + +// Release all previous images, and packs the images in imgs into state. The +// caller must check the change variables: +// *out_need_reposition == true: sub-image positions changed +// *out_need_upload == true: upload all sub-images again +// *out_need_reallocate == true: resize the EOSD texture to state->surface.w/h +// Logical implications: need_reallocate => need_upload => need_reposition +void eosd_packer_generate(struct eosd_packer *state, mp_eosd_images_t *imgs, + bool *out_need_reposition, bool *out_need_upload, + bool *out_need_reallocate) +{ + int i; + ASS_Image *img = imgs->imgs; + ASS_Image *p; + struct eosd_surface *sfc = &state->surface; + + *out_need_reposition = false; + *out_need_upload = false; + *out_need_reallocate = false; + + int change_state = imgs->changed; + + // eosd_reinit() was probably called, force full reupload. + if (state->targets_count == 0 && img) + change_state = 2; + + if (change_state == 0) + return; // Nothing changed, no need to redraw + + state->targets_count = 0; + + *out_need_reposition = true; + + if (!img) + return; // There's nothing to render! + + if (change_state == 1) + goto eosd_skip_upload; + + *out_need_upload = true; + while (1) { + for (p = img, i = 0; p; p = p->next) { + if (p->w <= 0 || p->h <= 0) + continue; + // Allocate new space for surface/target arrays + if (i >= state->targets_size) { + state->targets_size = FFMAX(state->targets_size * 2, 512); + state->targets = + talloc_realloc_size(state, state->targets, + state->targets_size + * sizeof(*state->targets)); + state->scratch = + talloc_realloc_size(state, state->scratch, + (state->targets_size + 16) + * sizeof(*state->scratch)); + } + state->targets[i].source.x1 = p->w + EOSD_PADDING; + state->targets[i].source.y1 = p->h + EOSD_PADDING; + i++; + } + if (pack_rectangles(state->targets, i, sfc->w, sfc->h, + state->scratch) >= 0) + break; + int w = FFMIN(FFMAX(sfc->w * 2, EOSD_SURFACE_INITIAL_SIZE), + state->max_surface_width); + int h = FFMIN(FFMAX(sfc->h * 2, EOSD_SURFACE_INITIAL_SIZE), + state->max_surface_height); + if (w == sfc->w && h == sfc->h) { + mp_msg(MSGT_VO, MSGL_ERR, "[eosd] EOSD bitmaps do not fit on " + "a surface with the maximum supported size\n"); + return; + } + sfc->w = w; + sfc->h = h; + *out_need_reallocate = true; + } + if (*out_need_reallocate) { + mp_msg(MSGT_VO, MSGL_V, "[eosd] Allocate a %dx%d surface for " + "EOSD bitmaps.\n", sfc->w, sfc->h); + } + +eosd_skip_upload: + for (p = img; p; p = p->next) { + if (p->w <= 0 || p->h <= 0) + continue; + struct eosd_target *target = &state->targets[state->targets_count]; + target->source.x1 -= EOSD_PADDING; + target->source.y1 -= EOSD_PADDING; + target->dest.x0 = p->dst_x; + target->dest.y0 = p->dst_y; + target->dest.x1 = p->w + p->dst_x; + target->dest.y1 = p->h + p->dst_y; + target->color = p->color; + target->ass_img = p; + state->targets_count++; + } +} + +// Calculate the bounding box of all sub-rectangles in the EOSD surface that +// will be used for EOSD rendering. +// If the bounding box is empty, return false. +bool eosd_packer_calculate_source_bb(struct eosd_packer *state, + struct eosd_rect *out_bb) +{ + struct eosd_rect bb = { state->surface.w, state->surface.h, 0, 0 }; + + for (int n = 0; n < state->targets_count; n++) { + struct eosd_rect s = state->targets[n].source; + bb.x0 = FFMIN(bb.x0, s.x0); + bb.y0 = FFMIN(bb.y0, s.y0); + bb.x1 = FFMAX(bb.x1, s.x1); + bb.y1 = FFMAX(bb.y1, s.y1); + } + + // avoid degenerate bounding box if empty + bb.x0 = FFMIN(bb.x0, bb.x1); + bb.y0 = FFMIN(bb.y0, bb.y1); + + *out_bb = bb; + return state->targets_count > 0; +} diff --git a/libvo/eosd_packer.h b/libvo/eosd_packer.h new file mode 100644 index 0000000000..e207a4a2dd --- /dev/null +++ b/libvo/eosd_packer.h @@ -0,0 +1,71 @@ +/* + * This file is part of mplayer2. + * + * mplayer2 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mplayer2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with mplayer2; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPLAYER_EOSD_PACKER_H +#define MPLAYER_EOSD_PACKER_H + +#include <inttypes.h> +#include <stdbool.h> + +#include "sub/ass_mp.h" + +// Pool of surfaces +struct eosd_surface { + //void *native_surface; + int w; + int h; +}; + +struct eosd_rect { + int x0, y0, x1, y1; +}; + +// List of surfaces to be rendered +struct eosd_target { + struct eosd_rect source; // position in EOSD surface + struct eosd_rect dest; // position on screen + uint32_t color; // libass-style color of the image + // NOTE: This must not be accessed after you return from your VO's + // VOCTRL_DRAW_EOSD call - libass will free or reuse the associated + // memory. Feel free to set this to NULL to make erroneous accesses to + // this member fail early. + ASS_Image *ass_img; +}; + +struct eosd_packer { + struct eosd_surface surface; + struct eosd_target *targets; + int targets_count; // number of valid elements in targets + int targets_size; // number of allocated elements in targets + + uint32_t max_surface_width; + uint32_t max_surface_height; + + int *scratch; +}; + +struct eosd_packer *eosd_packer_create(void *talloc_ctx); +void eosd_packer_reinit(struct eosd_packer *state, uint32_t max_width, + uint32_t max_height); +void eosd_packer_generate(struct eosd_packer *state, mp_eosd_images_t *imgs, + bool *out_need_reposition, bool *out_need_upload, + bool *out_need_reallocate); +bool eosd_packer_calculate_source_bb(struct eosd_packer *state, + struct eosd_rect *out_bb); + +#endif /* MPLAYER_EOSD_PACKER_H */ diff --git a/libvo/filter_kernels.c b/libvo/filter_kernels.c new file mode 100644 index 0000000000..2c2f56ee51 --- /dev/null +++ b/libvo/filter_kernels.c @@ -0,0 +1,279 @@ +/* + * This file is part of mplayer2. + * + * Most code for computing the weights is taken from Anti-Grain Geometry (AGG) + * (licensed under GPL 2 or later), with modifications. + * Copyright (C) 2002-2006 Maxim Shemanarev + * http://vector-agg.cvs.sourceforge.net/viewvc/vector-agg/agg-2.5/include/agg_image_filters.h?view=markup + * + * Also see glumpy (BSD licensed), contains the same code in Python: + * http://code.google.com/p/glumpy/source/browse/glumpy/image/filter.py + * + * Also see: Paul Heckbert |