Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(129)

Side by Side Diff: content/common/gpu/media/rendering_helper_egl.cc

Issue 10388108: Implement media::VideoDecodeAccelerator on Mac (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: address review comments Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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/rendering_helper.h"
6
7 #include <map>
8
9 #include "base/bind.h"
10 #include "base/mac/scoped_nsautorelease_pool.h"
11 #include "base/message_loop.h"
12 #include "base/stringize_macros.h"
13 #include "base/synchronization/waitable_event.h"
14 #include "third_party/angle/include/EGL/egl.h"
15
16 #if defined(OS_WIN)
17 #include "ui/gl/gl_bindings.h"
18 #include "ui/gl/gl_context.h"
19 #include "ui/gl/gl_implementation.h"
20 #include "ui/gl/gl_surface.h"
21 #else // OS_WIN
22 #include "third_party/angle/include/GLES2/gl2.h"
23 #endif // OS_WIN
24
25 // Helper for Shader creation.
26 static void CreateShader(GLuint program,
27 GLenum type,
28 const char* source,
29 int size) {
30 GLuint shader = glCreateShader(type);
31 glShaderSource(shader, 1, &source, &size);
32 glCompileShader(shader);
33 int result = GL_FALSE;
34 glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
35 if (!result) {
36 char log[4096];
37 glGetShaderInfoLog(shader, arraysize(log), NULL, log);
38 LOG(FATAL) << log;
39 }
40 glAttachShader(program, shader);
41 glDeleteShader(shader);
42 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
43 }
44
45 namespace video_test_util {
46
47 class RenderingHelperEGL : public RenderingHelper {
48 public:
49 RenderingHelperEGL();
50 virtual ~RenderingHelperEGL();
51
52 // Implement RenderingHelper.
53 virtual void Initialize(bool suppress_swap_to_display,
54 int num_windows,
55 int width,
56 int height,
57 base::WaitableEvent* done) OVERRIDE;
58 virtual void UnInitialize(base::WaitableEvent* done) OVERRIDE;
59 virtual void CreateTexture(int window_id,
60 uint32* texture_id,
61 base::WaitableEvent* done) OVERRIDE;
62 virtual void RenderTexture(uint32 texture_id) OVERRIDE;
63 virtual void DeleteTexture(uint32 texture_id) OVERRIDE;
64 virtual void* GetGLContext() OVERRIDE;
65 virtual void* GetGLDisplay() OVERRIDE;
66
67 private:
68 void Clear();
69
70 // Platform specific Init/Uninit.
71 void PlatformInitialize();
72 void PlatformUnInitialize();
73
74 // Platform specific window creation.
75 EGLNativeWindowType PlatformCreateWindow(int top_left_x, int top_left_y);
76
77 // Platform specific display surface returned here.
78 EGLDisplay PlatformGetDisplay();
79
80 MessageLoop* message_loop_;
81 int width_;
82 int height_;
83 bool suppress_swap_to_display_;
84
85 EGLDisplay egl_display_;
86 EGLContext egl_context_;
87 std::vector<EGLSurface> egl_surfaces_;
88 std::map<uint32, int> texture_id_to_surface_index_;
89
90 #if defined(OS_WIN)
91 std::vector<HWND> windows_;
92 #else // OS_WIN
93 Display* x_display_;
94 std::vector<Window> x_windows_;
95 #endif // OS_WIN
96 };
97
98 // static
99 RenderingHelper* RenderingHelper::Create() {
100 return new RenderingHelperEGL;
101 }
102
103 // static
104 void RenderingHelper::InitializePlatform() {
105 #if defined(OS_WIN)
106 gfx::InitializeGLBindings(gfx::kGLImplementationEGLGLES2);
107 gfx::GLSurface::InitializeOneOff();
108 {
109 // Hack to ensure that EGL extension function pointers are initialized.
110 scoped_refptr<gfx::GLSurface> surface(
111 gfx::GLSurface::CreateOffscreenGLSurface(false, gfx::Size(1, 1)));
112 scoped_refptr<gfx::GLContext> context(
113 gfx::GLContext::CreateGLContext(NULL, surface.get(),
114 gfx::PreferIntegratedGpu));
115 context->MakeCurrent(surface.get());
116 }
117 #endif // OS_WIN
118 }
119
120 RenderingHelperEGL::RenderingHelperEGL() {
121 Clear();
122 }
123
124 RenderingHelperEGL::~RenderingHelperEGL() {
125 CHECK_EQ(width_, 0) << "Must call UnInitialize before dtor.";
126 Clear();
127 }
128
129 void RenderingHelperEGL::Initialize(bool suppress_swap_to_display,
130 int num_windows,
131 int width,
132 int height,
133 base::WaitableEvent* done) {
134 // Use width_ != 0 as a proxy for the class having already been
135 // Initialize()'d, and UnInitialize() before continuing.
136 if (width_) {
137 base::WaitableEvent done(false, false);
138 UnInitialize(&done);
139 done.Wait();
140 }
141
142 suppress_swap_to_display_ = suppress_swap_to_display;
143 CHECK_GT(width, 0);
144 CHECK_GT(height, 0);
145 width_ = width;
146 height_ = height;
147 message_loop_ = MessageLoop::current();
148 CHECK_GT(num_windows, 0);
149
150 PlatformInitialize();
151
152 egl_display_ = PlatformGetDisplay();
153
154 EGLint major;
155 EGLint minor;
156 CHECK(eglInitialize(egl_display_, &major, &minor)) << eglGetError();
157 static EGLint rgba8888[] = {
158 EGL_RED_SIZE, 8,
159 EGL_GREEN_SIZE, 8,
160 EGL_BLUE_SIZE, 8,
161 EGL_ALPHA_SIZE, 8,
162 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
163 EGL_NONE,
164 };
165 EGLConfig egl_config;
166 int num_configs;
167 CHECK(eglChooseConfig(egl_display_, rgba8888, &egl_config, 1, &num_configs))
168 << eglGetError();
169 CHECK_GE(num_configs, 1);
170 static EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
171 egl_context_ = eglCreateContext(
172 egl_display_, egl_config, EGL_NO_CONTEXT, context_attribs);
173 CHECK_NE(egl_context_, EGL_NO_CONTEXT) << eglGetError();
174
175 // Per-window/surface X11 & EGL initialization.
176 for (int i = 0; i < num_windows; ++i) {
177 // Arrange X windows whimsically, with some padding.
178 int top_left_x = (width + 20) * (i % 4);
179 int top_left_y = (height + 12) * (i % 3);
180
181 EGLNativeWindowType window = PlatformCreateWindow(top_left_x, top_left_y);
182 EGLSurface egl_surface =
183 eglCreateWindowSurface(egl_display_, egl_config, window, NULL);
184 egl_surfaces_.push_back(egl_surface);
185 CHECK_NE(egl_surface, EGL_NO_SURFACE);
186 }
187 CHECK(eglMakeCurrent(egl_display_, egl_surfaces_[0],
188 egl_surfaces_[0], egl_context_)) << eglGetError();
189
190 static const float kVertices[] =
191 { -1.f, 1.f, -1.f, -1.f, 1.f, 1.f, 1.f, -1.f, };
192 static const float kTextureCoordsEgl[] = { 0, 1, 0, 0, 1, 1, 1, 0, };
193 static const char kVertexShader[] = STRINGIZE(
194 varying vec2 interp_tc;
195 attribute vec4 in_pos;
196 attribute vec2 in_tc;
197 void main() {
198 interp_tc = in_tc;
199 gl_Position = in_pos;
200 }
201 );
Ami GONE FROM CHROMIUM 2012/05/17 21:44:47 I realize you did this on rsesek's suggestion, but
sail 2012/05/23 23:02:29 Done.
sail 2012/05/23 23:02:29 Done.
202 static const char kFragmentShaderEgl[] = STRINGIZE(
203 precision mediump float;
204 varying vec2 interp_tc;
205 uniform sampler2D tex;
206 void main() {
207 gl_FragColor = texture2D(tex, interp_tc);
208 }
209 );
210 GLuint program = glCreateProgram();
211 CreateShader(program, GL_VERTEX_SHADER,
212 kVertexShader, arraysize(kVertexShader));
213 CreateShader(program, GL_FRAGMENT_SHADER,
214 kFragmentShaderEgl, arraysize(kFragmentShaderEgl));
215 glLinkProgram(program);
216 int result = GL_FALSE;
217 glGetProgramiv(program, GL_LINK_STATUS, &result);
218 if (!result) {
219 char log[4096];
220 glGetShaderInfoLog(program, arraysize(log), NULL, log);
221 LOG(FATAL) << log;
222 }
223 glUseProgram(program);
224 glDeleteProgram(program);
225
226 glUniform1i(glGetUniformLocation(program, "tex"), 0);
227 int pos_location = glGetAttribLocation(program, "in_pos");
228 glEnableVertexAttribArray(pos_location);
229 glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, kVertices);
230 int tc_location = glGetAttribLocation(program, "in_tc");
231 glEnableVertexAttribArray(tc_location);
232 glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0,
233 kTextureCoordsEgl);
234 done->Signal();
235 }
236
237 void RenderingHelperEGL::UnInitialize(base::WaitableEvent* done) {
238 CHECK_EQ(MessageLoop::current(), message_loop_);
239 CHECK(eglMakeCurrent(egl_display_, EGL_NO_SURFACE, EGL_NO_SURFACE,
240 EGL_NO_CONTEXT)) << eglGetError();
241 CHECK(eglDestroyContext(egl_display_, egl_context_));
242 for (size_t i = 0; i < egl_surfaces_.size(); ++i)
243 CHECK(eglDestroySurface(egl_display_, egl_surfaces_[i]));
244 CHECK(eglTerminate(egl_display_));
245 Clear();
246 done->Signal();
247 }
248
249 void RenderingHelperEGL::CreateTexture(int window_id,
250 uint32* texture_id,
251 base::WaitableEvent* done) {
252 if (MessageLoop::current() != message_loop_) {
253 message_loop_->PostTask(
254 FROM_HERE,
255 base::Bind(&RenderingHelper::CreateTexture, base::Unretained(this),
256 window_id, texture_id, done));
257 return;
258 }
259 CHECK(eglMakeCurrent(egl_display_, egl_surfaces_[window_id],
260 egl_surfaces_[window_id], egl_context_))
261 << eglGetError();
262 glGenTextures(1, texture_id);
263 glBindTexture(GL_TEXTURE_2D, *texture_id);
264 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA,
265 GL_UNSIGNED_BYTE, NULL);
266 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
267 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
268 // OpenGLES2.0.25 section 3.8.2 requires CLAMP_TO_EDGE for NPOT textures.
269 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
270 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
271 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
272 CHECK_EQ(static_cast<int>(eglGetError()), EGL_SUCCESS);
273 CHECK(texture_id_to_surface_index_.insert(
274 std::make_pair(*texture_id, window_id)).second);
275 done->Signal();
276 }
277
278 void RenderingHelperEGL::RenderTexture(uint32 texture_id) {
279 CHECK_EQ(MessageLoop::current(), message_loop_);
280 glActiveTexture(GL_TEXTURE0);
281 glBindTexture(GL_TEXTURE_2D, texture_id);
282 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
283 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
284 CHECK_EQ(static_cast<int>(eglGetError()), EGL_SUCCESS);
285 if (!suppress_swap_to_display_) {
286 int window_id = texture_id_to_surface_index_[texture_id];
287 CHECK(eglMakeCurrent(egl_display_, egl_surfaces_[window_id],
288 egl_surfaces_[window_id], egl_context_))
289 << eglGetError();
290 eglSwapBuffers(egl_display_, egl_surfaces_[window_id]);
291 }
292 CHECK_EQ(static_cast<int>(eglGetError()), EGL_SUCCESS);
293 }
294
295 void RenderingHelperEGL::DeleteTexture(uint32 texture_id) {
296 glDeleteTextures(1, &texture_id);
297 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
298 }
299
300 void* RenderingHelperEGL::GetGLContext() {
301 return egl_context_;
302 }
303
304 void* RenderingHelperEGL::GetGLDisplay() {
305 return egl_display_;
306 }
307
308 void RenderingHelperEGL::Clear() {
309 suppress_swap_to_display_ = false;
310 width_ = 0;
311 height_ = 0;
312 texture_id_to_surface_index_.clear();
313 message_loop_ = NULL;
314 egl_display_ = EGL_NO_DISPLAY;
315 egl_context_ = EGL_NO_CONTEXT;
316 egl_surfaces_.clear();
317 PlatformUnInitialize();
318 }
319
320 #if defined(OS_WIN)
321 void RenderingHelperEGL::PlatformInitialize() {}
322
323 void RenderingHelperEGL::PlatformUnInitialize() {
324 for (size_t i = 0; i < windows_.size(); ++i) {
325 DestroyWindow(windows_[i]);
326 }
327 windows_.clear();
328 }
329
330 EGLNativeWindowType RenderingHelperEGL::PlatformCreateWindow(
331 int top_left_x, int top_left_y) {
332 HWND window = CreateWindowEx(0, L"Static", L"VideoDecodeAcceleratorTest",
333 WS_OVERLAPPEDWINDOW | WS_VISIBLE, top_left_x,
334 top_left_y, width_, height_, NULL, NULL, NULL,
335 NULL);
336 CHECK(window != NULL);
337 windows_.push_back(window);
338 return window;
339 }
340
341 EGLDisplay RenderingHelperEGL::PlatformGetDisplay() {
342 return eglGetDisplay(EGL_DEFAULT_DISPLAY);
343 }
344
345 #else // OS_WIN
346
347 void RenderingHelperEGL::PlatformInitialize() {
348 CHECK(x_display_ = base::MessagePumpForUI::GetDefaultXDisplay());
349 }
350
351 void RenderingHelperEGL::PlatformUnInitialize() {
352 // Destroy resources acquired in Initialize, in reverse-acquisition order.
353 for (size_t i = 0; i < x_windows_.size(); ++i) {
354 CHECK(XUnmapWindow(x_display_, x_windows_[i]));
355 CHECK(XDestroyWindow(x_display_, x_windows_[i]));
356 }
357 // Mimic newly created object.
358 x_display_ = NULL;
359 x_windows_.clear();
360 }
361
362 EGLDisplay RenderingHelperEGL::PlatformGetDisplay() {
363 return eglGetDisplay(x_display_);
364 }
365
366 EGLNativeWindowType RenderingHelperEGL::PlatformCreateWindow(int top_left_x,
367 int top_left_y) {
368 int depth = DefaultDepth(x_display_, DefaultScreen(x_display_));
369
370 XSetWindowAttributes window_attributes;
371 window_attributes.background_pixel =
372 BlackPixel(x_display_, DefaultScreen(x_display_));
373 window_attributes.override_redirect = true;
374
375 Window x_window = XCreateWindow(
376 x_display_, DefaultRootWindow(x_display_),
377 top_left_x, top_left_y, width_, height_,
378 0 /* border width */,
379 depth, CopyFromParent /* class */, CopyFromParent /* visual */,
380 (CWBackPixel | CWOverrideRedirect), &window_attributes);
381 x_windows_.push_back(x_window);
382 XStoreName(x_display_, x_window, "VideoDecodeAcceleratorTest");
383 XSelectInput(x_display_, x_window, ExposureMask);
384 XMapWindow(x_display_, x_window);
385 return x_window;
386 }
387
388 #endif // OS_WIN
389
390 } // namespace video_test_util
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698