Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 | |
| OLD | NEW |