Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc
Commits
1930ef7e
Commit
1930ef7e
authored
Dec 06, 2009
by
Laurent Aimar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Splitted reusable code from opengl.c into opengl.h
It will be used by opengl vout_displays.
parent
a51b9608
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
519 additions
and
352 deletions
+519
-352
modules/video_output/opengl.c
modules/video_output/opengl.c
+90
-352
modules/video_output/opengl.h
modules/video_output/opengl.h
+429
-0
No files found.
modules/video_output/opengl.c
View file @
1930ef7e
...
...
@@ -32,58 +32,12 @@
# include "config.h"
#endif
#include <
errno.h>
/* ENOMEM */
#include <
assert.h>
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_vout.h>
#ifdef __APPLE__
# include <OpenGL/gl.h>
# include <OpenGL/glext.h>
#else
# include <GL/gl.h>
#endif
#ifndef YCBCR_MESA
# define YCBCR_MESA 0x8757
#endif
#ifndef UNSIGNED_SHORT_8_8_MESA
# define UNSIGNED_SHORT_8_8_MESA 0x85BA
#endif
/* RV16 */
#ifndef GL_UNSIGNED_SHORT_5_6_5
# define GL_UNSIGNED_SHORT_5_6_5 0x8363
#endif
#ifndef GL_CLAMP_TO_EDGE
# define GL_CLAMP_TO_EDGE 0x812F
#endif
#ifdef __APPLE__
/* On OS X, use GL_TEXTURE_RECTANGLE_EXT instead of GL_TEXTURE_2D.
This allows sizes which are not powers of 2 */
# define VLCGL_TARGET GL_TEXTURE_RECTANGLE_EXT
/* OS X OpenGL supports YUV. Hehe. */
# define VLCGL_FORMAT GL_YCBCR_422_APPLE
# define VLCGL_TYPE GL_UNSIGNED_SHORT_8_8_APPLE
#else
# define VLCGL_TARGET GL_TEXTURE_2D
/* RV32 */
# define VLCGL_RGB_FORMAT GL_RGBA
# define VLCGL_RGB_TYPE GL_UNSIGNED_BYTE
/* YUY2 */
# define VLCGL_YUV_FORMAT YCBCR_MESA
# define VLCGL_YUV_TYPE UNSIGNED_SHORT_8_8_MESA
/* Use RGB on Win32/GLX */
# define VLCGL_FORMAT VLCGL_RGB_FORMAT
# define VLCGL_TYPE VLCGL_RGB_TYPE
#endif
#include "opengl.h"
/*****************************************************************************
* Vout interface
...
...
@@ -97,9 +51,6 @@ static void Render ( vout_thread_t *, picture_t * );
static
void
DisplayVideo
(
vout_thread_t
*
,
picture_t
*
);
static
int
Control
(
vout_thread_t
*
,
int
,
va_list
);
static
inline
int
GetAlignedSize
(
int
);
static
int
InitTextures
(
vout_thread_t
*
);
static
int
SendEvents
(
vlc_object_t
*
,
char
const
*
,
vlc_value_t
,
vlc_value_t
,
void
*
);
...
...
@@ -132,12 +83,11 @@ vlc_module_end ()
struct
vout_sys_t
{
vout_thread_t
*
p_vout
;
vout_opengl_t
gl
;
vout_display_opengl_t
vgl
;
uint8_t
*
pp_buffer
[
2
];
int
i_index
;
int
i_tex_width
;
int
i_tex_height
;
GLuint
p_textures
[
2
];
picture_pool_t
*
p_pool
;
picture_t
*
p_current
;
};
/*****************************************************************************
...
...
@@ -154,19 +104,6 @@ static int CreateVout( vlc_object_t *p_this )
if
(
p_sys
==
NULL
)
return
VLC_ENOMEM
;
p_sys
->
i_index
=
0
;
#ifdef __APPLE__
p_sys
->
i_tex_width
=
p_vout
->
fmt_in
.
i_width
;
p_sys
->
i_tex_height
=
p_vout
->
fmt_in
.
i_height
;
#else
/* A texture must have a size aligned on a power of 2 */
p_sys
->
i_tex_width
=
GetAlignedSize
(
p_vout
->
fmt_in
.
i_width
);
p_sys
->
i_tex_height
=
GetAlignedSize
(
p_vout
->
fmt_in
.
i_height
);
#endif
msg_Dbg
(
p_vout
,
"Texture size: %dx%d"
,
p_sys
->
i_tex_width
,
p_sys
->
i_tex_height
);
/* Get window */
p_sys
->
p_vout
=
(
vout_thread_t
*
)
vlc_object_create
(
p_this
,
sizeof
(
vout_thread_t
)
);
...
...
@@ -237,64 +174,67 @@ static int CreateVout( vlc_object_t *p_this )
return
VLC_SUCCESS
;
}
static
int
OpenglLock
(
vout_opengl_t
*
gl
)
{
vout_thread_t
*
p_vout
=
gl
->
sys
;
if
(
!
p_vout
->
pf_lock
)
return
VLC_SUCCESS
;
return
p_vout
->
pf_lock
(
p_vout
);
}
static
void
OpenglUnlock
(
vout_opengl_t
*
gl
)
{
vout_thread_t
*
p_vout
=
gl
->
sys
;
if
(
p_vout
->
pf_unlock
)
p_vout
->
pf_unlock
(
p_vout
);
}
static
void
OpenglSwap
(
vout_opengl_t
*
gl
)
{
vout_thread_t
*
p_vout
=
gl
->
sys
;
p_vout
->
pf_swap
(
p_vout
);
}
/*****************************************************************************
* Init: initialize the OpenGL video thread output method
*****************************************************************************/
static
int
Init
(
vout_thread_t
*
p_vout
)
{
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
int
i_pixel_pitch
;
p_sys
->
p_vout
->
pf_init
(
p_sys
->
p_vout
);
/* TODO: We use YCbCr on Mac which is Y422, but on OSX it seems to == YUY2. Verify */
#if ( defined( WORDS_BIGENDIAN ) && VLCGL_FORMAT == GL_YCBCR_422_APPLE ) || (VLCGL_FORMAT == YCBCR_MESA)
p_vout
->
output
.
i_chroma
=
VLC_CODEC_YUYV
;
i_pixel_pitch
=
2
;
#elif defined( GL_YCBCR_422_APPLE ) && (VLCGL_FORMAT == GL_YCBCR_422_APPLE)
p_vout
->
output
.
i_chroma
=
VLC_CODEC_UYVY
;
i_pixel_pitch
=
2
;
#elif VLCGL_FORMAT == GL_RGB
# if VLCGL_TYPE == GL_UNSIGNED_BYTE
p_vout
->
output
.
i_chroma
=
VLC_CODEC_RGB24
;
# if defined( WORDS_BIGENDIAN )
p_vout
->
output
.
i_rmask
=
0x00ff0000
;
p_vout
->
output
.
i_gmask
=
0x0000ff00
;
p_vout
->
output
.
i_bmask
=
0x000000ff
;
# else
p_vout
->
output
.
i_rmask
=
0x000000ff
;
p_vout
->
output
.
i_gmask
=
0x0000ff00
;
p_vout
->
output
.
i_bmask
=
0x00ff0000
;
# endif
i_pixel_pitch
=
3
;
# else
p_vout
->
output
.
i_chroma
=
VLC_CODEC_RGB16
;
# if defined( WORDS_BIGENDIAN )
p_vout
->
output
.
i_rmask
=
0x001f
;
p_vout
->
output
.
i_gmask
=
0x07e0
;
p_vout
->
output
.
i_bmask
=
0xf800
;
# else
p_vout
->
output
.
i_rmask
=
0xf800
;
p_vout
->
output
.
i_gmask
=
0x07e0
;
p_vout
->
output
.
i_bmask
=
0x001f
;
# endif
i_pixel_pitch
=
2
;
# endif
#else
p_vout
->
output
.
i_chroma
=
VLC_CODEC_RGB32
;
# if defined( WORDS_BIGENDIAN )
p_vout
->
output
.
i_rmask
=
0xff000000
;
p_vout
->
output
.
i_gmask
=
0x00ff0000
;
p_vout
->
output
.
i_bmask
=
0x0000ff00
;
# else
p_vout
->
output
.
i_rmask
=
0x000000ff
;
p_vout
->
output
.
i_gmask
=
0x0000ff00
;
p_vout
->
output
.
i_bmask
=
0x00ff0000
;
# endif
i_pixel_pitch
=
4
;
#endif
p_sys
->
gl
.
lock
=
OpenglLock
;
p_sys
->
gl
.
unlock
=
OpenglUnlock
;
p_sys
->
gl
.
swap
=
OpenglSwap
;
p_sys
->
gl
.
sys
=
p_sys
->
p_vout
;
video_format_t
fmt
;
video_format_Setup
(
&
fmt
,
p_vout
->
render
.
i_chroma
,
p_vout
->
render
.
i_width
,
p_vout
->
render
.
i_height
,
p_vout
->
render
.
i_aspect
);
if
(
vout_display_opengl_Init
(
&
p_sys
->
vgl
,
&
fmt
,
&
p_sys
->
gl
)
)
{
I_OUTPUTPICTURES
=
0
;
return
VLC_EGENERIC
;
}
p_sys
->
p_pool
=
vout_display_opengl_GetPool
(
&
p_sys
->
vgl
);
if
(
!
p_sys
->
p_pool
)
{
vout_display_opengl_Clean
(
&
p_sys
->
vgl
);
I_OUTPUTPICTURES
=
0
;
return
VLC_EGENERIC
;
}
/* */
p_vout
->
output
.
i_chroma
=
fmt
.
i_chroma
;
p_vout
->
output
.
i_rmask
=
fmt
.
i_rmask
;
p_vout
->
output
.
i_gmask
=
fmt
.
i_gmask
;
p_vout
->
output
.
i_bmask
=
fmt
.
i_bmask
;
/* Since OpenGL can do rescaling for us, stick to the default
* coordinates and aspect. */
...
...
@@ -305,56 +245,22 @@ static int Init( vout_thread_t *p_vout )
p_vout
->
fmt_out
=
p_vout
->
fmt_in
;
p_vout
->
fmt_out
.
i_chroma
=
p_vout
->
output
.
i_chroma
;
/* We know the chroma, allocate one buffer which will be used
* directly by the decoder */
p_sys
->
pp_buffer
[
0
]
=
malloc
(
p_sys
->
i_tex_width
*
p_sys
->
i_tex_height
*
i_pixel_pitch
);
if
(
!
p_sys
->
pp_buffer
[
0
]
)
return
-
1
;
p_sys
->
pp_buffer
[
1
]
=
malloc
(
p_sys
->
i_tex_width
*
p_sys
->
i_tex_height
*
i_pixel_pitch
);
if
(
!
p_sys
->
pp_buffer
[
1
]
)
return
-
1
;
p_vout
->
p_picture
[
0
].
i_planes
=
1
;
p_vout
->
p_picture
[
0
].
p
->
p_pixels
=
p_sys
->
pp_buffer
[
0
];
p_vout
->
p_picture
[
0
].
p
->
i_lines
=
p_vout
->
output
.
i_height
;
p_vout
->
p_picture
[
0
].
p
->
i_visible_lines
=
p_vout
->
output
.
i_height
;
p_vout
->
p_picture
[
0
].
p
->
i_pixel_pitch
=
i_pixel_pitch
;
p_vout
->
p_picture
[
0
].
p
->
i_pitch
=
p_vout
->
output
.
i_width
*
p_vout
->
p_picture
[
0
].
p
->
i_pixel_pitch
;
p_vout
->
p_picture
[
0
].
p
->
i_visible_pitch
=
p_vout
->
output
.
i_width
*
p_vout
->
p_picture
[
0
].
p
->
i_pixel_pitch
;
/* */
p_sys
->
p_current
=
picture_pool_Get
(
p_sys
->
p_pool
);
msg_Err
(
p_vout
,
"pitch %d visible_p %d w %d"
,
p_sys
->
p_current
->
p
[
0
].
i_pitch
,
p_sys
->
p_current
->
p
[
0
].
i_visible_pitch
,
p_vout
->
render
.
i_width
);
p_vout
->
p_picture
[
0
]
=
*
p_sys
->
p_current
;
p_vout
->
p_picture
[
0
].
i_status
=
DESTROYED_PICTURE
;
p_vout
->
p_picture
[
0
].
i_type
=
DIRECT_PICTURE
;
PP_OUTPUTPICTURE
[
0
]
=
&
p_vout
->
p_picture
[
0
];
p_vout
->
p_picture
[
0
].
i_refcount
=
0
;
p_vout
->
p_picture
[
0
].
p_sys
=
NULL
;
PP_OUTPUTPICTURE
[
0
]
=
&
p_vout
->
p_picture
[
0
];
I_OUTPUTPICTURES
=
1
;
if
(
p_sys
->
p_vout
->
pf_lock
&&
p_sys
->
p_vout
->
pf_lock
(
p_sys
->
p_vout
)
)
{
msg_Warn
(
p_vout
,
"could not lock OpenGL provider"
);
return
0
;
}
InitTextures
(
p_vout
);
glDisable
(
GL_BLEND
);
glDisable
(
GL_DEPTH_TEST
);
glDepthMask
(
GL_FALSE
);
glDisable
(
GL_CULL_FACE
);
glClearColor
(
0
.
0
f
,
0
.
0
f
,
0
.
0
f
,
1
.
0
f
);
glClear
(
GL_COLOR_BUFFER_BIT
);
if
(
p_sys
->
p_vout
->
pf_unlock
)
{
p_sys
->
p_vout
->
pf_unlock
(
p_sys
->
p_vout
);
}
return
0
;
return
VLC_SUCCESS
;
}
/*****************************************************************************
...
...
@@ -364,24 +270,15 @@ static void End( vout_thread_t *p_vout )
{
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
if
(
p_sys
->
p_vout
->
pf_lock
&&
p_sys
->
p_vout
->
pf_lock
(
p_sys
->
p_vout
)
)
if
(
I_OUTPUTPICTURES
>
0
)
{
msg_Warn
(
p_vout
,
"could not lock OpenGL provider"
);
return
;
}
glFinish
();
glFlush
();
/* Free the texture buffer*/
glDeleteTextures
(
2
,
p_sys
->
p_textures
);
free
(
p_sys
->
pp_buffer
[
0
]
);
free
(
p_sys
->
pp_buffer
[
1
]
);
if
(
p_sys
->
p_current
)
picture_Release
(
p_sys
->
p_current
);
vout_display_opengl_Clean
(
&
p_sys
->
vgl
);
if
(
p_sys
->
p_vout
->
pf_unlock
)
{
p_sys
->
p_vout
->
pf_unlock
(
p_sys
->
p_vout
);
p_vout
->
p_picture
[
0
].
i_status
=
FREE_PICTURE
;
I_OUTPUTPICTURES
=
0
;
}
/* We must release the opengl provider here: opengl requiere init and end
...
...
@@ -437,25 +334,15 @@ static int Manage( vout_thread_t *p_vout )
p_vout
->
i_changes
=
p_sys
->
p_vout
->
i_changes
;
#ifdef __APPLE__
if
(
p_sys
->
p_vout
->
pf_lock
&&
p_sys
->
p_vout
->
pf_lock
(
p_sys
->
p_vout
)
)
{
msg_Warn
(
p_vout
,
"could not lock OpenGL provider"
);
return
i_ret
;
}
/* On OS X, we create the window and the GL view when entering
fullscreen - the textures have to be inited again */
if
(
i_fullscreen_change
)
{
InitTextures
(
p_vout
);
}
if
(
p_sys
->
p_vout
->
pf_unlock
)
{
p_sys
->
p_vout
->
pf_unlock
(
p_sys
->
p_vout
);
/* FIXME should we release p_current ? */
vout_display_opengl_ResetTextures
(
&
p_sys
->
vgl
);
}
#endif
// to align in real time in OPENGL
if
(
p_sys
->
p_vout
->
i_alignment
!=
p_vout
->
i_alignment
)
{
...
...
@@ -488,64 +375,21 @@ static int Manage( vout_thread_t *p_vout )
*****************************************************************************/
static
void
Render
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
)
{
VLC_UNUSED
(
p_pic
);
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
/* On Win32/GLX, we do this the usual way:
+ Fill the buffer with new content,
+ Reload the texture,
+ Use the texture.
On OS X with VRAM or AGP texturing, the order has to be:
+ Reload the texture,
+ Fill the buffer with new content,
+ Use the texture.
(Thanks to gcc from the Arstechnica forums for the tip)
Therefore, we have to use two buffers and textures. On Win32/GLX,
we reload the texture to be displayed and use it right away. On
OS X, we first render, then reload the texture to be used next
time. */
if
(
p_sys
->
p_vout
->
pf_lock
&&
p_sys
->
p_vout
->
pf_lock
(
p_sys
->
p_vout
)
)
if
(
p_sys
->
p_current
)
{
msg_Warn
(
p_vout
,
"could not lock OpenGL provider"
);
return
;
}
#ifdef __APPLE__
int
i_new_index
;
i_new_index
=
(
p_sys
->
i_index
+
1
)
&
1
;
/* Update the texture */
glBindTexture
(
VLCGL_TARGET
,
p_sys
->
p_textures
[
i_new_index
]
);
glTexSubImage2D
(
VLCGL_TARGET
,
0
,
0
,
0
,
p_vout
->
fmt_out
.
i_width
,
p_vout
->
fmt_out
.
i_height
,
VLCGL_FORMAT
,
VLCGL_TYPE
,
p_sys
->
pp_buffer
[
i_new_index
]
);
/* Bind to the previous texture for drawing */
glBindTexture
(
VLCGL_TARGET
,
p_sys
->
p_textures
[
p_sys
->
i_index
]
);
assert
(
p_sys
->
p_current
->
p
[
0
].
p_pixels
==
p_pic
->
p
[
0
].
p_pixels
);
/* Switch buffers */
p_sys
->
i_index
=
i_new_index
;
p_pic
->
p
->
p_pixels
=
p_sys
->
pp_buffer
[
p_sys
->
i_index
];
vout_display_opengl_Prepare
(
&
p_sys
->
vgl
,
p_sys
->
p_current
);
picture_Release
(
p_sys
->
p_current
)
;
}
#else
/* Update the texture */
glTexSubImage2D
(
GL_TEXTURE_2D
,
0
,
0
,
0
,
p_vout
->
fmt_out
.
i_width
,
p_vout
->
fmt_out
.
i_height
,
VLCGL_FORMAT
,
VLCGL_TYPE
,
p_sys
->
pp_buffer
[
0
]
);
#endif
p_sys
->
p_current
=
picture_pool_Get
(
p_sys
->
p_pool
);
if
(
p_sys
->
p_current
)
p_pic
->
p
[
0
].
p_pixels
=
p_sys
->
p_current
->
p
[
0
].
p_pixels
;
if
(
p_sys
->
p_vout
->
pf_unlock
)
{
p_sys
->
p_vout
->
pf_unlock
(
p_sys
->
p_vout
);
}
VLC_UNUSED
(
p_pic
);
}
/*****************************************************************************
...
...
@@ -553,68 +397,10 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic )
*****************************************************************************/
static
void
DisplayVideo
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
)
{
VLC_UNUSED
(
p_pic
);
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
float
f_width
,
f_height
,
f_x
,
f_y
;
if
(
p_sys
->
p_vout
->
pf_lock
&&
p_sys
->
p_vout
->
pf_lock
(
p_sys
->
p_vout
)
)
{
msg_Warn
(
p_vout
,
"could not lock OpenGL provider"
);
return
;
}
/* glTexCoord works differently with GL_TEXTURE_2D and
GL_TEXTURE_RECTANGLE_EXT */
#ifdef __APPLE__
f_x
=
(
float
)
p_vout
->
fmt_out
.
i_x_offset
;
f_y
=
(
float
)
p_vout
->
fmt_out
.
i_y_offset
;
f_width
=
(
float
)
p_vout
->
fmt_out
.
i_x_offset
+
(
float
)
p_vout
->
fmt_out
.
i_visible_width
;
f_height
=
(
float
)
p_vout
->
fmt_out
.
i_y_offset
+
(
float
)
p_vout
->
fmt_out
.
i_visible_height
;
#else
f_x
=
(
float
)
p_vout
->
fmt_out
.
i_x_offset
/
p_sys
->
i_tex_width
;
f_y
=
(
float
)
p_vout
->
fmt_out
.
i_y_offset
/
p_sys
->
i_tex_height
;
f_width
=
(
(
float
)
p_vout
->
fmt_out
.
i_x_offset
+
p_vout
->
fmt_out
.
i_visible_width
)
/
p_sys
->
i_tex_width
;
f_height
=
(
(
float
)
p_vout
->
fmt_out
.
i_y_offset
+
p_vout
->
fmt_out
.
i_visible_height
)
/
p_sys
->
i_tex_height
;
#endif
/* Why drawing here and not in Render()? Because this way, the
OpenGL providers can call pf_display to force redraw. Currently,
the OS X provider uses it to get a smooth window resizing */
glClear
(
GL_COLOR_BUFFER_BIT
);
glEnable
(
VLCGL_TARGET
);
glBegin
(
GL_POLYGON
);
glTexCoord2f
(
f_x
,
f_y
);
glVertex2f
(
-
1
.
0
,
1
.
0
);
glTexCoord2f
(
f_width
,
f_y
);
glVertex2f
(
1
.
0
,
1
.
0
);
glTexCoord2f
(
f_width
,
f_height
);
glVertex2f
(
1
.
0
,
-
1
.
0
);
glTexCoord2f
(
f_x
,
f_height
);
glVertex2f
(
-
1
.
0
,
-
1
.
0
);
glEnd
();
glDisable
(
VLCGL_TARGET
);
p_sys
->
p_vout
->
pf_swap
(
p_sys
->
p_vout
);
if
(
p_sys
->
p_vout
->
pf_unlock
)
{
p_sys
->
p_vout
->
pf_unlock
(
p_sys
->
p_vout
);
}
}
int
GetAlignedSize
(
int
i_size
)
{
/* Return the nearest power of 2 */
int
i_result
=
1
;
while
(
i_result
<
i_size
)
{
i_result
*=
2
;
}
return
i_result
;
vout_display_opengl_Display
(
&
p_sys
->
vgl
,
&
p_vout
->
fmt_out
);
VLC_UNUSED
(
p_pic
);
}
/*****************************************************************************
...
...
@@ -629,55 +415,6 @@ static int Control( vout_thread_t *p_vout, int i_query, va_list args )
return
VLC_EGENERIC
;
}
static
int
InitTextures
(
vout_thread_t
*
p_vout
)
{
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
int
i_index
;
glDeleteTextures
(
2
,
p_sys
->
p_textures
);
glGenTextures
(
2
,
p_sys
->
p_textures
);
for
(
i_index
=
0
;
i_index
<
2
;
i_index
++
)
{
glBindTexture
(
VLCGL_TARGET
,
p_sys
->
p_textures
[
i_index
]
);
/* Set the texture parameters */
glTexParameterf
(
VLCGL_TARGET
,
GL_TEXTURE_PRIORITY
,
1
.
0
);
glTexParameteri
(
VLCGL_TARGET
,
GL_TEXTURE_WRAP_S
,
GL_CLAMP_TO_EDGE
);
glTexParameteri
(
VLCGL_TARGET
,
GL_TEXTURE_WRAP_T
,
GL_CLAMP_TO_EDGE
);
glTexParameteri
(
VLCGL_TARGET
,
GL_TEXTURE_MAG_FILTER
,
GL_LINEAR
);
glTexParameteri
(
VLCGL_TARGET
,
GL_TEXTURE_MIN_FILTER
,
GL_LINEAR
);
glTexEnvf
(
GL_TEXTURE_ENV
,
GL_TEXTURE_ENV_MODE
,
GL_MODULATE
);
#ifdef __APPLE__
/* Tell the driver not to make a copy of the texture but to use
our buffer */
glEnable
(
GL_UNPACK_CLIENT_STORAGE_APPLE
);
glPixelStorei
(
GL_UNPACK_CLIENT_STORAGE_APPLE
,
GL_TRUE
);
#if 0
/* Use VRAM texturing */
glTexParameteri( VLCGL_TARGET, GL_TEXTURE_STORAGE_HINT_APPLE,
GL_STORAGE_CACHED_APPLE );
#else
/* Use AGP texturing */
glTexParameteri
(
VLCGL_TARGET
,
GL_TEXTURE_STORAGE_HINT_APPLE
,
GL_STORAGE_SHARED_APPLE
);
#endif
#endif
/* Call glTexImage2D only once, and use glTexSubImage2D later */
glTexImage2D
(
VLCGL_TARGET
,
0
,
3
,
p_sys
->
i_tex_width
,
p_sys
->
i_tex_height
,
0
,
VLCGL_FORMAT
,
VLCGL_TYPE
,
p_sys
->
pp_buffer
[
i_index
]
);
}
return
0
;
}
/*****************************************************************************
* SendEvents: forward mouse and keyboard events to the parent p_vout
*****************************************************************************/
...
...
@@ -687,3 +424,4 @@ static int SendEvents( vlc_object_t *p_this, char const *psz_var,
VLC_UNUSED
(
p_this
);
VLC_UNUSED
(
oldval
);
return
var_Set
(
(
vlc_object_t
*
)
_p_vout
,
psz_var
,
newval
);
}
modules/video_output/opengl.h
0 → 100644
View file @
1930ef7e
/*****************************************************************************
* opengl.h: OpenGL vout_display helpers
*****************************************************************************
* Copyright (C) 2004 the VideoLAN team
* Copyright (C) 2009 Laurent Aimar
* $Id$
*
* Authors: Cyril Deguet <asmax@videolan.org>
* Gildas Bazin <gbazin@videolan.org>
* Eric Petit <titer@m0k.org>
* Cedric Cocquebert <cedric.cocquebert@supelec.fr>
* Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include <vlc_common.h>
#include <vlc_picture_pool.h>
#include <vlc_vout_opengl.h>
#ifdef __APPLE__
# include <OpenGL/gl.h>
# include <OpenGL/glext.h>
#else
# include <GL/gl.h>
#endif
#ifndef YCBCR_MESA
# define YCBCR_MESA 0x8757
#endif
#ifndef UNSIGNED_SHORT_8_8_MESA
# define UNSIGNED_SHORT_8_8_MESA 0x85BA
#endif
/* RV16 */
#ifndef GL_UNSIGNED_SHORT_5_6_5
# define GL_UNSIGNED_SHORT_5_6_5 0x8363
#endif
#ifndef GL_CLAMP_TO_EDGE
# define GL_CLAMP_TO_EDGE 0x812F
#endif
#ifdef __APPLE__
/* On OS X, use GL_TEXTURE_RECTANGLE_EXT instead of GL_TEXTURE_2D.
This allows sizes which are not powers of 2 */
# define VLCGL_TARGET GL_TEXTURE_RECTANGLE_EXT
/* OS X OpenGL supports YUV. Hehe. */
# define VLCGL_FORMAT GL_YCBCR_422_APPLE
# define VLCGL_TYPE GL_UNSIGNED_SHORT_8_8_APPLE
# define VLCGL_TEXTURE_COUNT (2)
#else
# define VLCGL_TARGET GL_TEXTURE_2D
/* RV32 */
# define VLCGL_RGB_FORMAT GL_RGBA
# define VLCGL_RGB_TYPE GL_UNSIGNED_BYTE
/* YUY2 */
# define VLCGL_YUV_FORMAT YCBCR_MESA
# define VLCGL_YUV_TYPE UNSIGNED_SHORT_8_8_MESA
/* Use RGB on Win32/GLX */
# define VLCGL_FORMAT VLCGL_RGB_FORMAT
# define VLCGL_TYPE VLCGL_RGB_TYPE
# define VLCGL_TEXTURE_COUNT (1)
#endif
static
inline
int
GetAlignedSize
(
int
i_size
)
{
/* Return the nearest power of 2 */
int
i_result
=
1
;
while
(
i_result
<
i_size
)
i_result
*=
2
;
return
i_result
;
}
typedef
struct
{
vout_opengl_t
*
gl
;
video_format_t
fmt
;
int
tex_pixel_size
;
int
tex_width
;
int
tex_height
;
GLuint
texture
[
VLCGL_TEXTURE_COUNT
];
uint8_t
*
buffer
[
VLCGL_TEXTURE_COUNT
];
picture_pool_t
*
pool
;
}
vout_display_opengl_t
;
static
int
vout_display_opengl_Init
(
vout_display_opengl_t
*
vgl
,
video_format_t
*
fmt
,
vout_opengl_t
*
gl
)
{
vgl
->
gl
=
gl
;
/* Find the chroma we will use and update fmt */
/* TODO: We use YCbCr on Mac which is Y422, but on OSX it seems to == YUY2. Verify */
#if (defined(WORDS_BIGENDIAN) && VLCGL_FORMAT == GL_YCBCR_422_APPLE) || (VLCGL_FORMAT == YCBCR_MESA)
fmt
->
i_chroma
=
VLC_CODEC_YUYV
;
vgl
->
tex_pixel_size
=
2
;
#elif defined(GL_YCBCR_422_APPLE) && (VLCGL_FORMAT == GL_YCBCR_422_APPLE)
fmt
->
i_chroma
=
VLC_CODEC_UYVY
;
vgl
->
tex_pixel_size
=
2
;
#elif VLCGL_FORMAT == GL_RGB
# if VLCGL_TYPE == GL_UNSIGNED_BYTE
fmt
->
i_chroma
=
VLC_CODEC_RGB24
;
# if defined(WORDS_BIGENDIAN)
fmt
->
i_rmask
=
0x00ff0000
;
fmt
->
i_gmask
=
0x0000ff00
;
fmt
->
i_bmask
=
0x000000ff
;
# else
fmt
->
i_rmask
=
0x000000ff
;
fmt
->
i_gmask
=
0x0000ff00
;
fmt
->
i_bmask
=
0x00ff0000
;
# endif
vgl
->
tex_pixel_size
=
3
;
# else
fmt
->
i_chroma
=
VLC_CODEC_RGB16
;
# if defined(WORDS_BIGENDIAN)
fmt
->
i_rmask
=
0x001f
;
fmt
->
i_gmask
=
0x07e0
;
fmt
->
i_bmask
=
0xf800
;
# else
fmt
->
i_rmask
=
0xf800
;
fmt
->
i_gmask
=
0x07e0
;
fmt
->
i_bmask
=
0x001f
;
# endif
vgl
->
tex_pixel_size
=
2
;
# endif
#else
fmt
->
i_chroma
=
VLC_CODEC_RGB32
;
# if defined(WORDS_BIGENDIAN)
fmt
->
i_rmask
=
0xff000000
;
fmt
->
i_gmask
=
0x00ff0000
;
fmt
->
i_bmask
=
0x0000ff00
;
# else
fmt
->
i_rmask
=
0x000000ff
;
fmt
->
i_gmask
=
0x0000ff00
;
fmt
->
i_bmask
=
0x00ff0000
;
# endif
vgl
->
tex_pixel_size
=
4
;
#endif
vgl
->
fmt
=
*
fmt
;
/* Texture size */
#ifdef __APPLE__
vgl
->
tex_width
=
fmt
->
i_width
;
vgl
->
tex_height
=
fmt
->
i_height
;
#else
/* A texture must have a size aligned on a power of 2 */
vgl
->
tex_width
=
GetAlignedSize
(
fmt
->
i_width
);
vgl
->
tex_height
=
GetAlignedSize
(
fmt
->
i_height
);
#endif
/* */
for
(
int
i
=
0
;
i
<
VLCGL_TEXTURE_COUNT
;
i
++
)
{
vgl
->
texture
[
i
]
=
0
;
vgl
->
buffer
[
i
]
=
NULL
;
}
vgl
->
pool
=
NULL
;
/* */
if
(
!
vout_opengl_Lock
(
vgl
->
gl
))
{
glDisable
(
GL_BLEND
);
glDisable
(
GL_DEPTH_TEST
);
glDepthMask
(
GL_FALSE
);
glDisable
(
GL_CULL_FACE
);
glClearColor
(
0
.
0
f
,
0
.
0
f
,
0
.
0
f
,
1
.
0
f
);
glClear
(
GL_COLOR_BUFFER_BIT
);
vout_opengl_Unlock
(
vgl
->
gl
);
}
return
VLC_SUCCESS
;
}
static
void
vout_display_opengl_Clean
(
vout_display_opengl_t
*
vgl
)
{
/* */
if
(
!
vout_opengl_Lock
(
vgl
->
gl
))
{
glFinish
();
glFlush
();
glDeleteTextures
(
VLCGL_TEXTURE_COUNT
,
vgl
->
texture
);
vout_opengl_Unlock
(
vgl
->
gl
);
}
if
(
vgl
->
pool
)
{
picture_pool_Delete
(
vgl
->
pool
);
for
(
int
i
=
0
;
i
<
VLCGL_TEXTURE_COUNT
;
i
++
)
free
(
vgl
->
buffer
[
i
]);
}
}
static
int
vout_display_opengl_ResetTextures
(
vout_display_opengl_t
*
vgl
)
{
if
(
vout_opengl_Lock
(
vgl
->
gl
))
return
VLC_EGENERIC
;
glDeleteTextures
(
VLCGL_TEXTURE_COUNT
,
vgl
->
texture
);
glGenTextures
(
VLCGL_TEXTURE_COUNT
,
vgl
->
texture
);
for
(
int
i
=
0
;
i
<
VLCGL_TEXTURE_COUNT
;
i
++
)
{
glBindTexture
(
VLCGL_TARGET
,
vgl
->
texture
[
i
]);
/* Set the texture parameters */
glTexParameterf
(
VLCGL_TARGET
,
GL_TEXTURE_PRIORITY
,
1
.
0
);
glTexParameteri
(
VLCGL_TARGET
,
GL_TEXTURE_WRAP_S
,
GL_CLAMP_TO_EDGE
);
glTexParameteri
(
VLCGL_TARGET
,
GL_TEXTURE_WRAP_T
,
GL_CLAMP_TO_EDGE
);
glTexParameteri
(
VLCGL_TARGET
,
GL_TEXTURE_MAG_FILTER
,
GL_LINEAR
);
glTexParameteri
(
VLCGL_TARGET
,
GL_TEXTURE_MIN_FILTER
,
GL_LINEAR
);
glTexEnvf
(
GL_TEXTURE_ENV
,
GL_TEXTURE_ENV_MODE
,
GL_MODULATE
);
#ifdef __APPLE__
/* Tell the driver not to make a copy of the texture but to use
our buffer */
glEnable
(
GL_UNPACK_CLIENT_STORAGE_APPLE
);
glPixelStorei
(
GL_UNPACK_CLIENT_STORAGE_APPLE
,
GL_TRUE
);
#if 0
/* Use VRAM texturing */
glTexParameteri(VLCGL_TARGET, GL_TEXTURE_STORAGE_HINT_APPLE,
GL_STORAGE_CACHED_APPLE);
#else
/* Use AGP texturing */
glTexParameteri
(
VLCGL_TARGET
,
GL_TEXTURE_STORAGE_HINT_APPLE
,
GL_STORAGE_SHARED_APPLE
);
#endif
#endif
/* Call glTexImage2D only once, and use glTexSubImage2D later */
if
(
vgl
->
buffer
[
i
])
glTexImage2D
(
VLCGL_TARGET
,
0
,
3
,
vgl
->
tex_width
,
vgl
->
tex_height
,
0
,
VLCGL_FORMAT
,
VLCGL_TYPE
,
vgl
->
buffer
[
i
]);
}
vout_opengl_Unlock
(
vgl
->
gl
);
return
VLC_SUCCESS
;
}
#ifdef __APPLE__
/* XXX See comment vout_display_opengl_Prepare */
struct
picture_sys_t
{
vout_display_opengl_t
*
vgl
;
GLuint
texture
;
};
static
int
PictureLock
(
picture_t
*
picture
)
{
if
(
!
picture
->
p_sys
)
return
VLC_SUCCESS
;
vout_display_opengl_t
*
vgl
=
!
picture
->
p_sys
->
vgl
;
if
(
!
vout_opengl_Lock
(
vgl
->
gl
))
{
glBindTexture
(
VLCGL_TARGET
,
picture
->
p_sys
->
texture
);
glTexSubImage2D
(
VLCGL_TARGET
,
0
,
0
,
0
,
vgl
->
fmt
.
i_width
,
vgl
->
fmt
.
i_height
,
VLCGL_FORMAT
,
VLCGL_TYPE
,
picture
->
p
[
0
].
p_pixels
);
vout_opengl_Unlock
(
vgl
->
gl
);
}
return
VLC_SUCCESS
;
}
static
void
PictureUnlock
(
picture_t
*
picture
)
{
VLC_UNUSED
(
picture
);
}
#endif
static
picture_pool_t
*
vout_display_opengl_GetPool
(
vout_display_opengl_t
*
vgl
)
{
picture_t
*
picture
[
VLCGL_TEXTURE_COUNT
];
int
i
;
for
(
i
=
0
;
i
<
VLCGL_TEXTURE_COUNT
;
i
++
)
{
/* TODO memalign would be way better */
vgl
->
buffer
[
i
]
=
malloc
(
vgl
->
tex_width
*
vgl
->
tex_height
*
vgl
->
tex_pixel_size
);
if
(
!
vgl
->
buffer
[
i
])
break
;
picture_resource_t
rsc
;
memset
(
&
rsc
,
0
,
sizeof
(
rsc
));
#ifdef __APPLE__
rsc
.
p_sys
=
malloc
(
sizeof
(
*
rsc
.
p_sys
));
if
(
rsc
.
p_sys
)
rsc
.
p_sys
->
vgl
=
vgl
;
#endif
rsc
.
p
[
0
].
p_pixels
=
vgl
->
buffer
[
i
];
rsc
.
p
[
0
].
i_pitch
=
vgl
->
fmt
.
i_width
*
vgl
->
tex_pixel_size
;
rsc
.
p
[
0
].
i_lines
=
vgl
->
fmt
.
i_height
;
picture
[
i
]
=
picture_NewFromResource
(
&
vgl
->
fmt
,
&
rsc
);
if
(
!
picture
[
i
])
{
free
(
vgl
->
buffer
[
i
]);
vgl
->
buffer
[
i
]
=
NULL
;
break
;
}
}
if
(
i
<
VLCGL_TEXTURE_COUNT
)
goto
error
;
/* */
picture_pool_configuration_t
cfg
;
memset
(
&
cfg
,
0
,
sizeof
(
cfg
));
cfg
.
picture_count
=
i
;
cfg
.
picture
=
picture
;
#ifdef __APPLE__
cfg
.
lock
=
PictureLock
;
cfg
.
unlock
=
PictureUnlock
;
#endif
vgl
->
pool
=
picture_pool_NewExtended
(
&
cfg
);
if
(
!
vgl
->
pool
)
goto
error
;
vout_display_opengl_ResetTextures
(
vgl
);
return
vgl
->
pool
;
error:
for
(
int
j
=
0
;
j
<
i
;
j
++
)
{
picture_Delete
(
picture
[
j
]);
vgl
->
buffer
[
j
]
=
NULL
;
}
return
NULL
;
}
static
int
vout_display_opengl_Prepare
(
vout_display_opengl_t
*
vgl
,
picture_t
*
picture
)
{
/* On Win32/GLX, we do this the usual way:
+ Fill the buffer with new content,
+ Reload the texture,
+ Use the texture.
On OS X with VRAM or AGP texturing, the order has to be:
+ Reload the texture,
+ Fill the buffer with new content,
+ Use the texture.
(Thanks to gcc from the Arstechnica forums for the tip)
Therefore on OSX, we have to use two buffers and textures and use a
lock(/unlock) managed picture pool.
*/
if
(
vout_opengl_Lock
(
vgl
->
gl
))
return
VLC_EGENERIC
;
#ifdef __APPLE__
/* Bind to the texture for drawing */
glBindTexture
(
VLCGL_TARGET
,
picture
->
p_sys
->
texture
);
#else
/* Update the texture */
glTexSubImage2D
(
GL_TEXTURE_2D
,
0
,
0
,
0
,
vgl
->
fmt
.
i_width
,
vgl
->
fmt
.
i_height
,
VLCGL_FORMAT
,
VLCGL_TYPE
,
picture
->
p
[
0
].
p_pixels
);
#endif
vout_opengl_Unlock
(
vgl
->
gl
);
return
VLC_SUCCESS
;
}
static
int
vout_display_opengl_Display
(
vout_display_opengl_t
*
vgl
,
const
video_format_t
*
source
)
{
if
(
vout_opengl_Lock
(
vgl
->
gl
))
return
VLC_EGENERIC
;
/* glTexCoord works differently with GL_TEXTURE_2D and
GL_TEXTURE_RECTANGLE_EXT */
#if VLCGL_TARGET == GL_TEXTURE_2D
const
float
f_normw
=
vgl
->
tex_width
;
const
float
f_normh
=
vgl
->
tex_height
;
#else
assert
(
VLCGL_TARGET
==
GL_TEXTURE_RECTANGLE_EXT
);
const
float
f_normw
=
1
.
0
;
const
float
f_normh
=
1
.
0
;
#endif
float
f_x
=
(
source
->
i_x_offset
+
0
)
/
f_normw
;
float
f_y
=
(
source
->
i_y_offset
+
0
)
/
f_normh
;
float
f_width
=
(
source
->
i_x_offset
+
source
->
i_visible_width
)
/
f_normw
;
float
f_height
=
(
source
->
i_y_offset
+
source
->
i_visible_height
)
/
f_normh
;
/* Why drawing here and not in Render()? Because this way, the
OpenGL providers can call vout_display_opengl_Display to force redraw.i
Currently, the OS X provider uses it to get a smooth window resizing */
glClear
(
GL_COLOR_BUFFER_BIT
);
glEnable
(
VLCGL_TARGET
);
glBegin
(
GL_POLYGON
);
glTexCoord2f
(
f_x
,
f_y
);
glVertex2f
(
-
1
.
0
,
1
.
0
);
glTexCoord2f
(
f_width
,
f_y
);
glVertex2f
(
1
.
0
,
1
.
0
);
glTexCoord2f
(
f_width
,
f_height
);
glVertex2f
(
1
.
0
,
-
1
.
0
);
glTexCoord2f
(
f_x
,
f_height
);
glVertex2f
(
-
1
.
0
,
-
1
.
0
);
glEnd
();
glDisable
(
VLCGL_TARGET
);
vout_opengl_Swap
(
vgl
->
gl
);
vout_opengl_Unlock
(
vgl
->
gl
);
return
VLC_SUCCESS
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment