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

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

Issue 294663006: vda_unittest - Move the fps control from ThrottleVDAClient to RenderingHelper. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/common/gpu/media/rendering_helper.h" 5 #include "content/common/gpu/media/rendering_helper.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/mac/scoped_nsautorelease_pool.h" 8 #include "base/mac/scoped_nsautorelease_pool.h"
9 #include "base/message_loop/message_loop.h" 9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/stringize_macros.h" 10 #include "base/strings/stringize_macros.h"
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 void RenderingHelper::Initialize(const RenderingHelperParams& params, 90 void RenderingHelper::Initialize(const RenderingHelperParams& params,
91 base::WaitableEvent* done) { 91 base::WaitableEvent* done) {
92 // Use frame_dimensions_.size() != 0 as a proxy for the class having already 92 // Use frame_dimensions_.size() != 0 as a proxy for the class having already
93 // been Initialize()'d, and UnInitialize() before continuing. 93 // been Initialize()'d, and UnInitialize() before continuing.
94 if (frame_dimensions_.size()) { 94 if (frame_dimensions_.size()) {
95 base::WaitableEvent done(false, false); 95 base::WaitableEvent done(false, false);
96 UnInitialize(&done); 96 UnInitialize(&done);
97 done.Wait(); 97 done.Wait();
98 } 98 }
99 99
100 // TODO(owenlin): pass fps from params 100 frame_duration_ = params.rendering_fps > 0
101 frame_duration_ = base::TimeDelta::FromSeconds(1) / 60; 101 ? base::TimeDelta::FromSeconds(1) / params.rendering_fps
102 : base::TimeDelta();
102 103
103 gfx::InitializeStaticGLBindings(kGLImplementation); 104 gfx::InitializeStaticGLBindings(kGLImplementation);
104 scoped_refptr<gfx::GLContextStubWithExtensions> stub_context( 105 scoped_refptr<gfx::GLContextStubWithExtensions> stub_context(
105 new gfx::GLContextStubWithExtensions()); 106 new gfx::GLContextStubWithExtensions());
106 107
107 CHECK_GT(params.window_dimensions.size(), 0U); 108 CHECK_GT(params.window_dimensions.size(), 0U);
108 CHECK_EQ(params.frame_dimensions.size(), params.window_dimensions.size()); 109 CHECK_EQ(params.frame_dimensions.size(), params.window_dimensions.size());
109 frame_dimensions_ = params.frame_dimensions; 110 frame_dimensions_ = params.frame_dimensions;
110 render_as_thumbnails_ = params.render_as_thumbnails; 111 render_as_thumbnails_ = params.render_as_thumbnails;
111 message_loop_ = base::MessageLoop::current(); 112 message_loop_ = base::MessageLoop::current();
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 gl_display_, egl_config, EGL_NO_CONTEXT, context_attribs); 181 gl_display_, egl_config, EGL_NO_CONTEXT, context_attribs);
181 CHECK_NE(gl_context_, EGL_NO_CONTEXT) << eglGetError(); 182 CHECK_NE(gl_context_, EGL_NO_CONTEXT) << eglGetError();
182 stub_context->AddExtensionsString( 183 stub_context->AddExtensionsString(
183 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))); 184 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)));
184 stub_context->AddExtensionsString( 185 stub_context->AddExtensionsString(
185 eglQueryString(gl_display_, EGL_EXTENSIONS)); 186 eglQueryString(gl_display_, EGL_EXTENSIONS));
186 stub_context->SetGLVersionString( 187 stub_context->SetGLVersionString(
187 reinterpret_cast<const char*>(glGetString(GL_VERSION))); 188 reinterpret_cast<const char*>(glGetString(GL_VERSION)));
188 #endif 189 #endif
189 190
191 clients_.resize(params.num_windows);
190 // Per-window/surface X11 & EGL initialization. 192 // Per-window/surface X11 & EGL initialization.
191 for (int i = 0; i < params.num_windows; ++i) { 193 for (int i = 0; i < params.num_windows; ++i) {
192 // Arrange X windows whimsically, with some padding. 194 // Arrange X windows whimsically, with some padding.
193 int j = i % params.window_dimensions.size(); 195 int j = i % params.window_dimensions.size();
194 int width = params.window_dimensions[j].width(); 196 int width = params.window_dimensions[j].width();
195 int height = params.window_dimensions[j].height(); 197 int height = params.window_dimensions[j].height();
196 CHECK_GT(width, 0); 198 CHECK_GT(width, 0);
197 CHECK_GT(height, 0); 199 CHECK_GT(height, 0);
198 int top_left_x = (width + 20) * (i % 4); 200 int top_left_x = (width + 20) * (i % 4);
199 int top_left_y = (height + 12) * (i % 3); 201 int top_left_y = (height + 12) * (i % 3);
200 render_areas_.push_back(gfx::Rect( 202 render_areas_.push_back(gfx::Rect(
201 top_left_x, top_left_y, width, height)); 203 top_left_x, top_left_y, width, height));
202
203 // Initialize to an invalid texture id: 0 to indicate no texture
204 // for rendering.
205 texture_ids_.push_back(0);
206 texture_targets_.push_back(0);
207 } 204 }
208 205
209 #if defined(OS_WIN) 206 #if defined(OS_WIN)
210 window_ = CreateWindowEx(0, L"Static", L"VideoDecodeAcceleratorTest", 207 window_ = CreateWindowEx(0, L"Static", L"VideoDecodeAcceleratorTest",
211 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 208 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0,
212 window_size.width(), widow_size.height(), 209 window_size.width(), widow_size.height(),
213 NULL, NULL, NULL, NULL); 210 NULL, NULL, NULL, NULL);
214 CHECK(window_ != NULL); 211 CHECK(window_ != NULL);
215 #else 212 #else
216 int depth = DefaultDepth(x_display_, DefaultScreen(x_display_)); 213 int depth = DefaultDepth(x_display_, DefaultScreen(x_display_));
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 GL_COLOR_ATTACHMENT0, 281 GL_COLOR_ATTACHMENT0,
285 GL_TEXTURE_2D, 282 GL_TEXTURE_2D,
286 thumbnails_texture_id_, 283 thumbnails_texture_id_,
287 0); 284 0);
288 285
289 GLenum fb_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); 286 GLenum fb_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
290 CHECK(fb_status == GL_FRAMEBUFFER_COMPLETE) << fb_status; 287 CHECK(fb_status == GL_FRAMEBUFFER_COMPLETE) << fb_status;
291 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 288 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
292 glClear(GL_COLOR_BUFFER_BIT); 289 glClear(GL_COLOR_BUFFER_BIT);
293 glBindFramebufferEXT(GL_FRAMEBUFFER, 0); 290 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
294
295 // In render_as_thumbnails_ mode, we render the FBO content on the
296 // screen instead of the decoded textures.
297 texture_targets_[0] = GL_TEXTURE_2D;
298 texture_ids_[0] = thumbnails_texture_id_;
299 } 291 }
300 292
301 // These vertices and texture coords. map (0,0) in the texture to the 293 // These vertices and texture coords. map (0,0) in the texture to the
302 // bottom left of the viewport. Since we get the video frames with the 294 // bottom left of the viewport. Since we get the video frames with the
303 // the top left at (0,0) we need to flip the texture y coordinate 295 // the top left at (0,0) we need to flip the texture y coordinate
304 // in the vertex shader for this to be rendered the right way up. 296 // in the vertex shader for this to be rendered the right way up.
305 // In the case of thumbnail rendering we use the same vertex shader 297 // In the case of thumbnail rendering we use the same vertex shader
306 // to render the FBO the screen, where we do not want this flipping. 298 // to render the FBO the screen, where we do not want this flipping.
307 static const float kVertices[] = 299 static const float kVertices[] =
308 { -1.f, 1.f, -1.f, -1.f, 1.f, 1.f, 1.f, -1.f, }; 300 { -1.f, 1.f, -1.f, -1.f, 1.f, 1.f, 1.f, -1.f, };
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 if (tex_external != -1) { 360 if (tex_external != -1) {
369 glUniform1i(tex_external, 1); 361 glUniform1i(tex_external, 1);
370 } 362 }
371 int pos_location = glGetAttribLocation(program_, "in_pos"); 363 int pos_location = glGetAttribLocation(program_, "in_pos");
372 glEnableVertexAttribArray(pos_location); 364 glEnableVertexAttribArray(pos_location);
373 glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, kVertices); 365 glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, kVertices);
374 int tc_location = glGetAttribLocation(program_, "in_tc"); 366 int tc_location = glGetAttribLocation(program_, "in_tc");
375 glEnableVertexAttribArray(tc_location); 367 glEnableVertexAttribArray(tc_location);
376 glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, kTextureCoords); 368 glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, kTextureCoords);
377 369
378 render_timer_.Start(FROM_HERE, frame_duration_, this, 370 if (frame_duration_ != base::TimeDelta()) {
379 &RenderingHelper::RenderContent); 371 render_timer_.Start(FROM_HERE, frame_duration_, this,
372 &RenderingHelper::RenderContent);
373 }
380 done->Signal(); 374 done->Signal();
381 } 375 }
382 376
383 void RenderingHelper::UnInitialize(base::WaitableEvent* done) { 377 void RenderingHelper::UnInitialize(base::WaitableEvent* done) {
384 CHECK_EQ(base::MessageLoop::current(), message_loop_); 378 CHECK_EQ(base::MessageLoop::current(), message_loop_);
385 render_timer_.Stop(); 379 render_timer_.Stop();
386 if (render_as_thumbnails_) { 380 if (render_as_thumbnails_) {
387 glDeleteTextures(1, &thumbnails_texture_id_); 381 glDeleteTextures(1, &thumbnails_texture_id_);
388 glDeleteFramebuffersEXT(1, &thumbnails_fbo_id_); 382 glDeleteFramebuffersEXT(1, &thumbnails_fbo_id_);
389 } 383 }
390 #if GL_VARIANT_GLX 384 #if GL_VARIANT_GLX
391 385
392 glXDestroyContext(x_display_, gl_context_); 386 glXDestroyContext(x_display_, gl_context_);
393 #else // EGL 387 #else // EGL
394 CHECK(eglDestroyContext(gl_display_, gl_context_)); 388 CHECK(eglDestroyContext(gl_display_, gl_context_));
395 CHECK(eglDestroySurface(gl_display_, gl_surface_)); 389 CHECK(eglDestroySurface(gl_display_, gl_surface_));
396 CHECK(eglTerminate(gl_display_)); 390 CHECK(eglTerminate(gl_display_));
397 #endif 391 #endif
398 gfx::ClearGLBindings(); 392 gfx::ClearGLBindings();
399 Clear(); 393 Clear();
400 done->Signal(); 394 done->Signal();
401 } 395 }
402 396
397 void RenderingHelper::SetClient(int window_id, RenderingClient *client) {
398 if (base::MessageLoop::current() != message_loop_) {
399 message_loop_->PostTask(
400 FROM_HERE,
401 base::Bind(&RenderingHelper::SetClient, base::Unretained(this),
402 window_id, client));
403 return;
404 }
405 clients_[window_id] = client;
406 }
407
403 void RenderingHelper::CreateTexture(int window_id, 408 void RenderingHelper::CreateTexture(int window_id,
404 uint32 texture_target, 409 uint32 texture_target,
405 uint32* texture_id, 410 uint32* texture_id,
406 base::WaitableEvent* done) { 411 base::WaitableEvent* done) {
407 if (base::MessageLoop::current() != message_loop_) { 412 if (base::MessageLoop::current() != message_loop_) {
408 message_loop_->PostTask( 413 message_loop_->PostTask(
409 FROM_HERE, 414 FROM_HERE,
410 base::Bind(&RenderingHelper::CreateTexture, base::Unretained(this), 415 base::Bind(&RenderingHelper::CreateTexture, base::Unretained(this),
411 window_id, texture_target, texture_id, done)); 416 window_id, texture_target, texture_id, done));
412 return; 417 return;
(...skipping 16 matching lines...) Expand all
429 glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 434 glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
430 // OpenGLES2.0.25 section 3.8.2 requires CLAMP_TO_EDGE for NPOT textures. 435 // OpenGLES2.0.25 section 3.8.2 requires CLAMP_TO_EDGE for NPOT textures.
431 glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 436 glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
432 glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 437 glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
433 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); 438 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
434 CHECK(texture_id_to_surface_index_.insert( 439 CHECK(texture_id_to_surface_index_.insert(
435 std::make_pair(*texture_id, window_id)).second); 440 std::make_pair(*texture_id, window_id)).second);
436 done->Signal(); 441 done->Signal();
437 } 442 }
438 443
444 // Helper function to set GL viewport.
445 static inline void GLSetViewPort(const gfx::Rect& area) {
446 glViewport(area.x(), area.y(), area.width(), area.height());
447 glScissor(area.x(), area.y(), area.width(), area.height());
448 }
449
450 void RenderingHelper::RenderThumbnail(uint32 texture_target,
451 uint32 texture_id) {
452 CHECK_EQ(base::MessageLoop::current(), message_loop_);
453 const int width = thumbnail_size_.width();
454 const int height = thumbnail_size_.height();
455 const int thumbnails_in_row = thumbnails_fbo_size_.width() / width;
456 const int thumbnails_in_column = thumbnails_fbo_size_.height() / height;
457 const int row = (frame_count_ / thumbnails_in_row) % thumbnails_in_column;
458 const int col = frame_count_ % thumbnails_in_row;
459
460 gfx::Rect area(col * width, row * height, width, height);
461
462 glUniform1i(glGetUniformLocation(program_, "tex_flip"), 0);
463 glBindFramebufferEXT(GL_FRAMEBUFFER, thumbnails_fbo_id_);
464 GLSetViewPort(area);
465 RenderTexture(texture_target, texture_id);
466 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
467 ++frame_count_;
468 }
439 469
440 void RenderingHelper::RenderTexture(uint32 texture_target, uint32 texture_id) { 470 void RenderingHelper::RenderTexture(uint32 texture_target, uint32 texture_id) {
441 CHECK_EQ(base::MessageLoop::current(), message_loop_);
442 if (texture_id == 0)
443 return;
444
445 if (render_as_thumbnails_) {
446 const int width = thumbnail_size_.width();
447 const int height = thumbnail_size_.height();
448 const int thumbnails_in_row = thumbnails_fbo_size_.width() / width;
449 const int thumbnails_in_column = thumbnails_fbo_size_.height() / height;
450 const int row = (frame_count_ / thumbnails_in_row) % thumbnails_in_column;
451 const int col = frame_count_ % thumbnails_in_row;
452
453 gfx::Rect area(col * width, row * height, width, height);
454
455 glUniform1i(glGetUniformLocation(program_, "tex_flip"), 0);
456 glBindFramebufferEXT(GL_FRAMEBUFFER, thumbnails_fbo_id_);
457 DrawTexture(area, texture_target, texture_id);
458 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
459 ++frame_count_;
460 } else {
461 size_t window_id = texture_id_to_surface_index_[texture_id];
462 texture_targets_[window_id] = texture_target;
463 texture_ids_[window_id] = texture_id;
464 }
465 }
466
467 void RenderingHelper::DrawTexture(const gfx::Rect& area,
468 uint32 texture_target,
469 uint32 texture_id) {
470 glViewport(area.x(), area.y(), area.width(), area.height());
471 glScissor(area.x(), area.y(), area.width(), area.height());
472
473 // Unbound texture samplers default to (0, 0, 0, 1). Use this fact to switch 471 // Unbound texture samplers default to (0, 0, 0, 1). Use this fact to switch
474 // between GL_TEXTURE_2D and GL_TEXTURE_EXTERNAL_OES as appopriate. 472 // between GL_TEXTURE_2D and GL_TEXTURE_EXTERNAL_OES as appopriate.
475 if (texture_target == GL_TEXTURE_2D) { 473 if (texture_target == GL_TEXTURE_2D) {
476 glActiveTexture(GL_TEXTURE0 + 0); 474 glActiveTexture(GL_TEXTURE0 + 0);
477 glBindTexture(GL_TEXTURE_2D, texture_id); 475 glBindTexture(GL_TEXTURE_2D, texture_id);
478 glActiveTexture(GL_TEXTURE0 + 1); 476 glActiveTexture(GL_TEXTURE0 + 1);
479 glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0); 477 glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
480 } else if (texture_target == GL_TEXTURE_EXTERNAL_OES) { 478 } else if (texture_target == GL_TEXTURE_EXTERNAL_OES) {
481 glActiveTexture(GL_TEXTURE0 + 0); 479 glActiveTexture(GL_TEXTURE0 + 0);
482 glBindTexture(GL_TEXTURE_2D, 0); 480 glBindTexture(GL_TEXTURE_2D, 0);
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 *rgb_ptr++ = *rgba_ptr++; 562 *rgb_ptr++ = *rgba_ptr++;
565 solid = solid && (*rgba_ptr == 0xff); 563 solid = solid && (*rgba_ptr == 0xff);
566 rgba_ptr++; 564 rgba_ptr++;
567 } 565 }
568 *alpha_solid = solid; 566 *alpha_solid = solid;
569 567
570 done->Signal(); 568 done->Signal();
571 } 569 }
572 570
573 void RenderingHelper::RenderContent() { 571 void RenderingHelper::RenderContent() {
572
574 glUniform1i(glGetUniformLocation(program_, "tex_flip"), 1); 573 glUniform1i(glGetUniformLocation(program_, "tex_flip"), 1);
575 for (size_t i = 0; i < render_areas_.size(); ++i) { 574
576 DrawTexture(render_areas_[i], texture_targets_[i], texture_ids_[i]); 575 if (render_as_thumbnails_) {
576 // In render_as_thumbnails_ mode, we render the FBO content on the
577 // screen instead of the decoded textures.
578 GLSetViewPort(render_areas_[0]);
579 RenderTexture(GL_TEXTURE_2D, thumbnails_texture_id_);
580 } else {
581 for (size_t i = 0; i < clients_.size(); ++i) {
582 RenderingClient *client = clients_[i];
583 if (client != NULL) {
584 GLSetViewPort(render_areas_[i]);
585 client->RenderContent(this);
586 }
587 }
577 } 588 }
578 589
579 #if GL_VARIANT_GLX 590 #if GL_VARIANT_GLX
580 glXSwapBuffers(x_display_, x_window_); 591 glXSwapBuffers(x_display_, x_window_);
581 #else // EGL 592 #else // EGL
582 eglSwapBuffers(gl_display_, gl_surface_); 593 eglSwapBuffers(gl_display_, gl_surface_);
583 CHECK_EQ(static_cast<int>(eglGetError()), EGL_SUCCESS); 594 CHECK_EQ(static_cast<int>(eglGetError()), EGL_SUCCESS);
584 #endif 595 #endif
585 } 596 }
586 } // namespace content 597 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698