summaryrefslogtreecommitdiffstats
path: root/libvo
diff options
context:
space:
mode:
Diffstat (limited to 'libvo')
-rw-r--r--libvo/cocoa_common.h3
-rw-r--r--libvo/cocoa_common.m47
-rw-r--r--libvo/d3d_shader_yuv.h142
-rw-r--r--libvo/d3d_shader_yuv.hlsl44
-rw-r--r--libvo/d3d_shader_yuv_2ch.h170
-rw-r--r--libvo/eosd_packer.c254
-rw-r--r--libvo/eosd_packer.h71
-rw-r--r--libvo/filter_kernels.c279
-rw-r--r--libvo/filter_kernels.h45
-rw-r--r--libvo/gl_common.c845
-rw-r--r--libvo/gl_common.h342
-rw-r--r--libvo/gl_header_fixes.h231
-rw-r--r--libvo/mga_template.c2
-rw-r--r--libvo/video_out.c16
-rw-r--r--libvo/vo_direct3d.c2137
-rw-r--r--libvo/vo_directfb2.c14
-rw-r--r--libvo/vo_directx.c1732
-rw-r--r--libvo/vo_gl.c326
-rw-r--r--libvo/vo_gl3.c2418
-rw-r--r--libvo/vo_gl3_shaders.glsl316
-rw-r--r--libvo/vo_kva.c2
-rw-r--r--libvo/vo_svga.c4
-rw-r--r--libvo/vo_vdpau.c255
-rw-r--r--libvo/w32_common.c228
-rw-r--r--libvo/x11_common.c3
25 files changed, 7618 insertions, 2308 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's "zoom"
+ *
+ * Also see XBMC: ConvolutionKernels.cpp etc.
+ *
+ * mplayer2 is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by</