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

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

Powered by Google App Engine
This is Rietveld 408576698