add gnash_la_CPPFLAGS to see if it makes distcheck happy
[gnash.git] / libvaapi / VaapiSurface.cpp
blob08f09018bce611d4c7d41c8c516dfaa07bd6bfee
1 // VaapiSurface.cpp: VA 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 <algorithm>
21 #include <boost/cstdint.hpp>
23 #include "log.h"
24 #include "VaapiSurface.h"
25 #include "VaapiGlobalContext.h"
26 #include "VaapiImage.h"
27 #include "VaapiSubpicture.h"
28 #include "vaapi_utils.h"
30 extern "C" {
31 #include <libswscale/swscale.h>
34 namespace gnash {
36 VaapiSurfaceImplBase::VaapiSurfaceImplBase(unsigned int width, unsigned int height)
37 : _surface(VA_INVALID_SURFACE), _width(width), _height(height)
41 class VaapiSurfaceImpl: public VaapiSurfaceImplBase {
42 public:
43 VaapiSurfaceImpl(const VaapiSurface *surface, unsigned int width, unsigned int height);
44 ~VaapiSurfaceImpl();
47 VaapiSurfaceImpl::VaapiSurfaceImpl(const VaapiSurface */* surface */,
48 unsigned int width, unsigned int height)
49 : VaapiSurfaceImplBase(width, height)
51 GNASH_REPORT_FUNCTION;
53 if (width == 0 || height == 0) {
54 return;
57 VaapiGlobalContext * gvactx = VaapiGlobalContext::get();
58 if (!gvactx) {
59 return;
62 VAStatus status;
63 VASurfaceID surface_id;
64 status = vaCreateSurfaces(gvactx->display(),
65 width, height, VA_RT_FORMAT_YUV420,
66 1, &surface_id);
67 if (!vaapi_check_status(status, "vaCreateSurfaces()")) {
68 return;
71 reset(surface_id);
72 // log_debug(" -> surface 0x%08x\n", surface());
75 VaapiSurfaceImpl::~VaapiSurfaceImpl()
77 log_debug("VaapiSurface::~VaapiSurface(): surface 0x%08x\n", surface());
79 if (surface() == VA_INVALID_SURFACE) {
80 return;
83 VaapiGlobalContext * gvactx = VaapiGlobalContext::get();
84 if (!gvactx) {
85 return;
88 VAStatus status;
89 VASurfaceID surface_id = surface();
90 status = vaDestroySurfaces(gvactx->display(), &surface_id, 1);
91 if (!vaapi_check_status(status, "vaDestroySurfaces()")) {
92 return;
95 reset(VA_INVALID_SURFACE);
98 VaapiSurface::VaapiSurface(unsigned int width, unsigned int height)
99 : _impl(new VaapiSurfaceImpl(this, width, height))
100 , _context(NULL)
104 // Clear surface with black color
105 void VaapiSurface::clear()
107 VaapiImage background(width(), height(), VAAPI_IMAGE_NV12);
109 if (!background.map()) {
110 return;
113 // 0x10 is the black level for Y
114 boost::uint8_t *Y = background.getPlane(0);
115 unsigned int i, stride = background.getPitch(0);
116 for (i = 0; i < background.height(); i++, Y += stride) {
117 memset(Y, 0x10, stride);
120 // 0x80 is the black level for Cb and Cr
121 boost::uint8_t *UV = background.getPlane(1);
122 stride = background.getPitch(1);
123 for (i = 0; i < background.height()/2; i++, UV += stride) {
124 memset(UV, 0x80, stride);
127 background.unmap();
129 VaapiGlobalContext * gvactx = VaapiGlobalContext::get();
130 if (!gvactx) {
131 return;
134 VAStatus status;
135 status = vaPutImage(gvactx->display(), get(), background.get(),
136 0, 0, background.width(), background.height(),
137 0, 0, width(), height());
138 if (!vaapi_check_status(status, "vaPutImage()")) {
139 return;
143 // Compare two subpictures
144 static inline bool operator== (boost::shared_ptr<VaapiSubpicture> const &a,
145 boost::shared_ptr<VaapiSubpicture> const &b)
147 return a->get() == b->get();
150 // Associate subpicture to the surface
151 bool VaapiSurface::associateSubpicture(boost::shared_ptr<VaapiSubpicture> subpicture,
152 VaapiRectangle const & src_rect,
153 VaapiRectangle const & dst_rect)
155 VaapiGlobalContext * gvactx = VaapiGlobalContext::get();
156 if (!gvactx) {
157 return false;
160 deassociateSubpicture(subpicture);
162 VAStatus status;
163 VASurfaceID surface_id = this->get();
164 status = vaAssociateSubpicture(gvactx->display(), subpicture->get(),
165 &surface_id, 1,
166 src_rect.x, src_rect.y,
167 src_rect.width, src_rect.height,
168 dst_rect.x, dst_rect.y,
169 dst_rect.width, dst_rect.height,
171 if (!vaapi_check_status(status, "vaAssociateSubpicture()")) {
172 return false;
174 _subpictures.push_back(subpicture);
176 return true;
179 // Deassociate subpicture from the surface
180 bool VaapiSurface::deassociateSubpicture(boost::shared_ptr<VaapiSubpicture> subpicture)
182 std::vector< boost::shared_ptr<VaapiSubpicture> >::iterator it;
183 it = std::find(_subpictures.begin(), _subpictures.end(), subpicture);
184 if (it == _subpictures.end()) {
185 return false;
187 _subpictures.erase(it);
189 VaapiGlobalContext * gvactx = VaapiGlobalContext::get();
190 if (!gvactx) {
191 return false;
194 VAStatus status;
195 VASurfaceID surface_id = this->get();
196 status = vaDeassociateSubpicture(gvactx->display(), subpicture->get(),
197 &surface_id, 1);
198 if (!vaapi_check_status(status, "vaDeassociateSubpicture()")) {
199 return false;
202 return true;
205 } // end of gnash namespace
207 // local Variables:
208 // mode: C++
209 // indent-tabs-mode: nil
210 // End: