1 // VaapiSurfaceGLX.cpp: VA/GLX surface abstraction
3 // Copyright (C) 2009, 2010 Free Software Foundation, Inc.
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #include <va/va_glx.h>
21 #include <va/va_x11.h>
24 #include "VaapiSurfaceGLX.h"
25 #include "VaapiGlobalContext.h"
26 #include "vaapi_utils.h"
30 // Returns a string representation of an OpenGL error
31 static const char *gl_get_error_string(GLenum error
)
38 { GL_NO_ERROR
, "no error" },
39 { GL_INVALID_ENUM
, "invalid enumerant" },
40 { GL_INVALID_VALUE
, "invalid value" },
41 { GL_INVALID_OPERATION
, "invalid operation" },
42 { GL_STACK_OVERFLOW
, "stack overflow" },
43 { GL_STACK_UNDERFLOW
, "stack underflow" },
44 { GL_OUT_OF_MEMORY
, "out of memory" },
45 #ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT
46 { GL_INVALID_FRAMEBUFFER_OPERATION_EXT
, "invalid framebuffer operation" },
52 for (i
= 0; gl_errors
[i
].str
; i
++) {
53 if (gl_errors
[i
].val
== error
) {
54 return gl_errors
[i
].str
;
60 static inline bool gl_do_check_error(int report
)
63 bool is_error
= false;
64 while ((error
= glGetError()) != GL_NO_ERROR
) {
66 vaapi_dprintf("glError: %s caught\n", gl_get_error_string(error
));
73 static inline void gl_purge_errors(void)
78 static inline bool gl_check_error(void)
80 return gl_do_check_error(1);
85 // glGetIntegerv() wrapper
86 static bool gl_get_param(GLenum param
, unsigned int *pval
)
91 glGetIntegerv(param
, &val
);
92 if (gl_check_error()) {
101 /// OpenGL texture state
102 struct TextureState
{
104 unsigned int old_texture
;
105 unsigned int was_enabled
: 1;
106 unsigned int was_bound
: 1;
109 /// Bind texture, preserve previous texture state
110 static bool bind_texture(TextureState
*ts
, GLenum target
, GLuint texture
)
115 ts
->was_enabled
= glIsEnabled(target
);
117 GLenum texture_binding
;
120 texture_binding
= GL_TEXTURE_BINDING_1D
;
123 texture_binding
= GL_TEXTURE_BINDING_2D
;
126 texture_binding
= GL_TEXTURE_BINDING_3D
;
128 case GL_TEXTURE_RECTANGLE_ARB
:
129 texture_binding
= GL_TEXTURE_BINDING_RECTANGLE_ARB
;
136 if (!ts
->was_enabled
) {
138 } else if (gl_get_param(texture_binding
, &ts
->old_texture
)) {
139 ts
->was_bound
= texture
== ts
->old_texture
;
144 if (!ts
->was_bound
) {
146 glBindTexture(target
, texture
);
147 if (gl_check_error()) {
154 /// Release texture, restore previous texture state
155 static void unbind_texture(TextureState
*ts
)
157 if (!ts
->was_bound
&& ts
->old_texture
) {
158 glBindTexture(ts
->target
, ts
->old_texture
);
160 if (!ts
->was_enabled
) {
161 glDisable(ts
->target
);
169 class VaapiSurfaceGLXImpl
: public VaapiSurfaceImplBase
{
170 void *surface() const
171 { return reinterpret_cast<void *>(VaapiSurfaceImplBase::surface()); }
174 VaapiSurfaceGLXImpl(GLenum target
, GLuint texture
);
175 ~VaapiSurfaceGLXImpl();
177 bool update(boost::shared_ptr
<VaapiSurface
> surface
);
180 VaapiSurfaceGLXImpl::VaapiSurfaceGLXImpl(GLenum target
, GLuint texture
)
181 : VaapiSurfaceImplBase(0, 0)
183 GNASH_REPORT_FUNCTION
;
187 if (target
== 0 || texture
== 0) {
191 VaapiGlobalContext
* gvactx
= VaapiGlobalContext::get();
197 void *surface
= NULL
;
198 status
= vaCreateSurfaceGLX(gvactx
->display(), target
, texture
, &surface
);
199 if (!vaapi_check_status(status
, "vaCreateSurfaceGLX()")) {
203 reset(reinterpret_cast<uintptr_t>(surface
));
205 log_debug(" -> surface %p\n", this->surface());
208 VaapiSurfaceGLXImpl::~VaapiSurfaceGLXImpl()
210 // GNASH_REPORT_FUNCTION;
212 log_debug("VaapiSurface::~VaapiSurface(): surface %p\n", surface());
218 VaapiGlobalContext
* gvactx
= VaapiGlobalContext::get();
224 status
= vaDestroySurfaceGLX(gvactx
->display(), surface());
225 if (!vaapi_check_status(status
, "vaDestroySurfaceGLX()")) {
232 bool VaapiSurfaceGLXImpl::update(boost::shared_ptr
<VaapiSurface
> surface
)
234 GNASH_REPORT_FUNCTION
;
236 if (!this->surface()) {
240 VaapiGlobalContext
* gvactx
= VaapiGlobalContext::get();
246 status
= vaSyncSurface(gvactx
->display(), surface
->get());
247 if (!vaapi_check_status(status
, "vaSyncSurface()"))
250 status
= vaCopySurfaceGLX(gvactx
->display(), this->surface(),
251 surface
->get(), VA_FRAME_PICTURE
);
252 if (!vaapi_check_status(status
, "vaCopySurfaceGLX()")) {
259 VaapiSurfaceGLX::VaapiSurfaceGLX(GLenum target
, GLuint texture
)
260 : _impl(new VaapiSurfaceGLXImpl(target
, texture
))
264 bool VaapiSurfaceGLX::update(boost::shared_ptr
<VaapiSurface
> surface
)
266 log_debug("VaapiSurfaceGLX::update(): from surface 0x%08x\n", surface
->get());
268 return dynamic_cast<VaapiSurfaceGLXImpl
*>(_impl
.get())->update(surface
);
271 } // end of gnash namespace
275 // indent-tabs-mode: nil