OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "content/common/gpu/media/vaapi_picture_provider_x11.h" | |
6 #include "third_party/libva/va/va_x11.h" | |
7 #include "ui/gl/gl_bindings.h" | |
8 #include "ui/gl/gl_context_glx.h" | |
9 #include "ui/gl/gl_image.h" | |
10 #include "ui/gl/scoped_binders.h" | |
11 | |
12 namespace content { | |
13 | |
14 #define LOG_VA_ERROR_AND_RETURN(input, err_msg) \ | |
15 do { \ | |
16 VAStatus va_status = input; \ | |
17 if (va_status != VA_STATUS_SUCCESS) { \ | |
18 DVLOG(1) << err_msg << " : " << vaErrorStr(va_status); \ | |
19 return false; \ | |
20 } \ | |
21 } while (0) | |
22 | |
23 class TFPPicture : public VaapiPictureProvider::Picture { | |
24 public: | |
25 TFPPicture(VADisplay va_display, | |
26 gfx::GLContextGLX* glx_context, | |
27 const base::Callback<bool(void)> make_context_current, | |
28 int32 picture_buffer_id, | |
29 uint32 texture_id, | |
30 const gfx::Size& size) | |
31 : Picture(picture_buffer_id, texture_id, size), | |
32 va_display_(va_display), | |
33 glx_context_(glx_context), | |
34 make_context_current_(make_context_current), | |
35 x_display_(glx_context_->display()) {} | |
36 | |
37 virtual ~TFPPicture() { | |
38 if (glx_pixmap_ && make_context_current_.Run()) { | |
39 glXReleaseTexImageEXT(x_display_, glx_pixmap_, GLX_FRONT_LEFT_EXT); | |
40 glXDestroyPixmap(x_display_, glx_pixmap_); | |
41 } | |
42 | |
43 if (x_pixmap_) | |
44 XFreePixmap(x_display_, x_pixmap_); | |
45 XSync(x_display_, False); // Needed to work around buggy vdpau-driver. | |
46 } | |
47 | |
48 bool Initialize(GLXFBConfig& fb_config) { | |
49 if (!make_context_current_.Run()) | |
50 return false; | |
51 | |
52 XWindowAttributes win_attr; | |
53 int screen = DefaultScreen(x_display_); | |
54 XGetWindowAttributes(x_display_, RootWindow(x_display_, screen), &win_attr); | |
55 // TODO(posciak): pass the depth required by libva, not the RootWindow's | |
56 // depth | |
57 x_pixmap_ = XCreatePixmap(x_display_, | |
58 RootWindow(x_display_, screen), | |
59 size().width(), | |
60 size().height(), | |
61 win_attr.depth); | |
62 if (!x_pixmap_) { | |
63 DVLOG(1) << "Failed creating an X Pixmap for TFP"; | |
64 return false; | |
65 } | |
66 | |
67 static const int pixmap_attr[] = { | |
68 GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, GLX_TEXTURE_FORMAT_EXT, | |
69 GLX_TEXTURE_FORMAT_RGB_EXT, GL_NONE, | |
70 }; | |
71 | |
72 glx_pixmap_ = | |
73 glXCreatePixmap(x_display_, fb_config, x_pixmap_, pixmap_attr); | |
74 if (!glx_pixmap_) { | |
75 // x_pixmap_ will be freed in the destructor. | |
76 DVLOG(1) << "Failed creating a GLX Pixmap for TFP"; | |
77 return false; | |
78 } | |
79 | |
80 return true; | |
81 } | |
82 | |
83 bool PutSurface(VASurfaceID va_surface_id) OVERRIDE { | |
84 if (!make_context_current_.Run()) { | |
85 DVLOG(1) << "Failed making gl context current"; | |
86 return false; | |
87 } | |
88 | |
89 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id()); | |
90 glXBindTexImageEXT(x_display_, glx_pixmap_, GLX_FRONT_LEFT_EXT, NULL); | |
91 if (glGetError() != GL_NO_ERROR) | |
92 return false; | |
93 | |
94 LOG_VA_ERROR_AND_RETURN(vaPutSurface(va_display_, | |
Pawel Osciak
2014/10/08 08:17:22
Could we please keep using the VaapiWrapper instan
llandwerlin-old
2014/10/08 09:31:18
Acknowledged.
| |
95 va_surface_id, | |
96 x_pixmap_, | |
97 0, | |
98 0, | |
99 size().width(), | |
100 size().height(), | |
101 0, | |
102 0, | |
103 size().width(), | |
104 size().height(), | |
105 NULL, | |
106 0, | |
107 0), | |
108 "Couldn't put surface into picture"); | |
109 return true; | |
110 } | |
111 | |
112 private: | |
113 VADisplay va_display_; | |
114 | |
115 gfx::GLContextGLX* glx_context_; | |
116 base::Callback<bool(void)> make_context_current_; | |
117 Display* x_display_; | |
118 | |
119 Pixmap x_pixmap_; | |
120 GLXPixmap glx_pixmap_; | |
121 }; | |
122 | |
123 class XFreeDeleter { | |
124 public: | |
125 void operator()(void* x) const { ::XFree(x); } | |
126 }; | |
127 | |
128 X11VaapiPictureProvider::X11VaapiPictureProvider( | |
129 VADisplay va_display, | |
130 gfx::GLContextGLX* glx_context, | |
131 const base::Callback<bool(void)> make_context_current) | |
132 : glx_context_(glx_context), | |
133 make_context_current_(make_context_current), | |
134 x_display_(glx_context_->display()), | |
135 va_display_(va_display) { | |
136 } | |
137 | |
138 X11VaapiPictureProvider::~X11VaapiPictureProvider() { | |
139 } | |
140 | |
141 scoped_ptr<VaapiPictureProvider::Picture> | |
142 X11VaapiPictureProvider::CreatePicture(int32 picture_buffer_id, | |
143 uint32 texture_id, | |
144 const gfx::Size& size) { | |
145 TFPPicture* tfp_picture = new TFPPicture(va_display_, | |
146 glx_context_, | |
147 make_context_current_, | |
148 picture_buffer_id, | |
149 texture_id, | |
150 size); | |
151 scoped_ptr<VaapiPictureProvider::Picture> picture(tfp_picture); | |
152 | |
153 if (!tfp_picture->Initialize(fb_config_)) | |
154 picture.reset(); | |
155 | |
156 return picture.Pass(); | |
157 } | |
158 | |
159 bool X11VaapiPictureProvider::SetCodedSurfacesSize(const gfx::Size& size) { | |
160 return true; | |
161 } | |
162 | |
163 bool X11VaapiPictureProvider::Initialize() { | |
164 if (!make_context_current_.Run()) { | |
165 DVLOG(1) << "Couldn't make context current"; | |
166 return false; | |
167 } | |
168 | |
169 const int fbconfig_attr[] = { | |
170 GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, | |
171 GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT, | |
172 GLX_BIND_TO_TEXTURE_RGB_EXT, GL_TRUE, | |
173 GLX_Y_INVERTED_EXT, GL_TRUE, | |
174 GL_NONE, | |
175 }; | |
176 | |
177 int num_fbconfigs; | |
178 scoped_ptr<GLXFBConfig, XFreeDeleter> glx_fb_configs(glXChooseFBConfig( | |
179 x_display_, DefaultScreen(x_display_), fbconfig_attr, &num_fbconfigs)); | |
180 | |
181 if (!glx_fb_configs) { | |
182 DVLOG(1) << "Couldn't get glx configs"; | |
183 return false; | |
184 } | |
185 if (!num_fbconfigs) { | |
186 DVLOG(1) << "Couldn't get at least a glx config"; | |
187 return false; | |
188 } | |
189 | |
190 fb_config_ = glx_fb_configs.get()[0]; | |
191 return true; | |
192 } | |
193 | |
194 } // namespace content | |
OLD | NEW |