don't add (LIBLTDL) to LDFLAGS, libltdl is part of libgnashbase.
[gnash.git] / libvaapi / VaapiSurfaceGLX.cpp
blob6d24e8891b8e26ae439db4e1f64edbfa23604230
1 // VaapiSurfaceGLX.cpp: VA/GLX surface abstraction
2 //
3 // Copyright (C) 2009, 2010 Free Software Foundation, Inc.
4 //
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.
9 //
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.
14 //
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>
23 #include "log.h"
24 #include "VaapiSurfaceGLX.h"
25 #include "VaapiGlobalContext.h"
26 #include "vaapi_utils.h"
28 namespace gnash {
30 // Returns a string representation of an OpenGL error
31 static const char *gl_get_error_string(GLenum error)
33 static const struct {
34 GLenum val;
35 const char *str;
37 gl_errors[] = {
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" },
47 #endif
48 { ~0, NULL }
51 int i;
52 for (i = 0; gl_errors[i].str; i++) {
53 if (gl_errors[i].val == error) {
54 return gl_errors[i].str;
57 return "unknown";
60 static inline bool gl_do_check_error(int report)
62 GLenum error;
63 bool is_error = false;
64 while ((error = glGetError()) != GL_NO_ERROR) {
65 if (report) {
66 vaapi_dprintf("glError: %s caught\n", gl_get_error_string(error));
68 is_error = true;
70 return is_error;
73 static inline void gl_purge_errors(void)
75 gl_do_check_error(0);
78 static inline bool gl_check_error(void)
80 return gl_do_check_error(1);
83 #if 0
85 // glGetIntegerv() wrapper
86 static bool gl_get_param(GLenum param, unsigned int *pval)
88 GLint val;
90 gl_purge_errors();
91 glGetIntegerv(param, &val);
92 if (gl_check_error()) {
93 return false;
95 if (pval) {
96 *pval = val;
98 return true;
101 /// OpenGL texture state
102 struct TextureState {
103 unsigned int target;
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)
112 ts->target = target;
113 ts->old_texture = 0;
114 ts->was_bound = 0;
115 ts->was_enabled = glIsEnabled(target);
117 GLenum texture_binding;
118 switch (target) {
119 case GL_TEXTURE_1D:
120 texture_binding = GL_TEXTURE_BINDING_1D;
121 break;
122 case GL_TEXTURE_2D:
123 texture_binding = GL_TEXTURE_BINDING_2D;
124 break;
125 case GL_TEXTURE_3D:
126 texture_binding = GL_TEXTURE_BINDING_3D;
127 break;
128 case GL_TEXTURE_RECTANGLE_ARB:
129 texture_binding = GL_TEXTURE_BINDING_RECTANGLE_ARB;
130 break;
131 default:
132 assert(!target);
133 return false;
136 if (!ts->was_enabled) {
137 glEnable(target);
138 } else if (gl_get_param(texture_binding, &ts->old_texture)) {
139 ts->was_bound = texture == ts->old_texture;
140 } else {
141 return false;
144 if (!ts->was_bound) {
145 gl_purge_errors();
146 glBindTexture(target, texture);
147 if (gl_check_error()) {
148 return false;
151 return true;
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);
164 gl_check_error();
167 #endif
169 class VaapiSurfaceGLXImpl: public VaapiSurfaceImplBase {
170 void *surface() const
171 { return reinterpret_cast<void *>(VaapiSurfaceImplBase::surface()); }
173 public:
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;
185 reset(0);
187 if (target == 0 || texture == 0) {
188 return;
191 VaapiGlobalContext * gvactx = VaapiGlobalContext::get();
192 if (!gvactx) {
193 return;
196 VAStatus status;
197 void *surface = NULL;
198 status = vaCreateSurfaceGLX(gvactx->display(), target, texture, &surface);
199 if (!vaapi_check_status(status, "vaCreateSurfaceGLX()")) {
200 return;
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());
214 if (!surface()) {
215 return;
218 VaapiGlobalContext * gvactx = VaapiGlobalContext::get();
219 if (!gvactx) {
220 return;
223 VAStatus status;
224 status = vaDestroySurfaceGLX(gvactx->display(), surface());
225 if (!vaapi_check_status(status, "vaDestroySurfaceGLX()")) {
226 return;
229 reset(0);
232 bool VaapiSurfaceGLXImpl::update(boost::shared_ptr<VaapiSurface> surface)
234 GNASH_REPORT_FUNCTION;
236 if (!this->surface()) {
237 return false;
240 VaapiGlobalContext * gvactx = VaapiGlobalContext::get();
241 if (!gvactx) {
242 return false;
245 VAStatus status;
246 status = vaSyncSurface(gvactx->display(), surface->get());
247 if (!vaapi_check_status(status, "vaSyncSurface()"))
248 return false;
250 status = vaCopySurfaceGLX(gvactx->display(), this->surface(),
251 surface->get(), VA_FRAME_PICTURE);
252 if (!vaapi_check_status(status, "vaCopySurfaceGLX()")) {
253 return false;
256 return true;
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
273 // local Variables:
274 // mode: C++
275 // indent-tabs-mode: nil
276 // End: