1 // VaapiSurface.cpp: VA 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
21 #include <boost/cstdint.hpp>
24 #include "VaapiSurface.h"
25 #include "VaapiGlobalContext.h"
26 #include "VaapiImage.h"
27 #include "VaapiSubpicture.h"
28 #include "vaapi_utils.h"
31 #include <libswscale/swscale.h>
36 VaapiSurfaceImplBase::VaapiSurfaceImplBase(unsigned int width
, unsigned int height
)
37 : _surface(VA_INVALID_SURFACE
), _width(width
), _height(height
)
41 class VaapiSurfaceImpl
: public VaapiSurfaceImplBase
{
43 VaapiSurfaceImpl(const VaapiSurface
*surface
, unsigned int width
, unsigned int height
);
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) {
57 VaapiGlobalContext
* gvactx
= VaapiGlobalContext::get();
63 VASurfaceID surface_id
;
64 status
= vaCreateSurfaces(gvactx
->display(),
65 width
, height
, VA_RT_FORMAT_YUV420
,
67 if (!vaapi_check_status(status
, "vaCreateSurfaces()")) {
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
) {
83 VaapiGlobalContext
* gvactx
= VaapiGlobalContext::get();
89 VASurfaceID surface_id
= surface();
90 status
= vaDestroySurfaces(gvactx
->display(), &surface_id
, 1);
91 if (!vaapi_check_status(status
, "vaDestroySurfaces()")) {
95 reset(VA_INVALID_SURFACE
);
98 VaapiSurface::VaapiSurface(unsigned int width
, unsigned int height
)
99 : _impl(new VaapiSurfaceImpl(this, width
, height
))
104 // Clear surface with black color
105 void VaapiSurface::clear()
107 VaapiImage
background(width(), height(), VAAPI_IMAGE_NV12
);
109 if (!background
.map()) {
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
);
129 VaapiGlobalContext
* gvactx
= VaapiGlobalContext::get();
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()")) {
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();
160 deassociateSubpicture(subpicture
);
163 VASurfaceID surface_id
= this->get();
164 status
= vaAssociateSubpicture(gvactx
->display(), subpicture
->get(),
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()")) {
174 _subpictures
.push_back(subpicture
);
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()) {
187 _subpictures
.erase(it
);
189 VaapiGlobalContext
* gvactx
= VaapiGlobalContext::get();
195 VASurfaceID surface_id
= this->get();
196 status
= vaDeassociateSubpicture(gvactx
->display(), subpicture
->get(),
198 if (!vaapi_check_status(status
, "vaDeassociateSubpicture()")) {
205 } // end of gnash namespace
209 // indent-tabs-mode: nil