| OLD | NEW |
| 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 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 uniform bool tex_flip; | 323 uniform bool tex_flip; |
| 324 void main() { | 324 void main() { |
| 325 if (tex_flip) | 325 if (tex_flip) |
| 326 interp_tc = vec2(in_tc.x, 1.0 - in_tc.y); | 326 interp_tc = vec2(in_tc.x, 1.0 - in_tc.y); |
| 327 else | 327 else |
| 328 interp_tc = in_tc; | 328 interp_tc = in_tc; |
| 329 gl_Position = in_pos; | 329 gl_Position = in_pos; |
| 330 }); | 330 }); |
| 331 | 331 |
| 332 #if GL_VARIANT_EGL | 332 #if GL_VARIANT_EGL |
| 333 static const char kFragmentShader[] = | 333 static const char kFragmentShader[] = STRINGIZE( |
| 334 "#extension GL_OES_EGL_image_external : enable\n" | 334 precision mediump float; |
| 335 "precision mediump float;\n" | 335 varying vec2 interp_tc; |
| 336 "varying vec2 interp_tc;\n" | 336 uniform sampler2D tex; |
| 337 "uniform sampler2D tex;\n" | 337 void main() { |
| 338 "#ifdef GL_OES_EGL_image_external\n" | 338 gl_FragColor = texture2D(tex, interp_tc); |
| 339 "uniform samplerExternalOES tex_external;\n" | 339 }); |
| 340 "#endif\n" | |
| 341 "void main() {\n" | |
| 342 " vec4 color = texture2D(tex, interp_tc);\n" | |
| 343 "#ifdef GL_OES_EGL_image_external\n" | |
| 344 " color += texture2D(tex_external, interp_tc);\n" | |
| 345 "#endif\n" | |
| 346 " gl_FragColor = color;\n" | |
| 347 "}\n"; | |
| 348 #else | 340 #else |
| 349 static const char kFragmentShader[] = STRINGIZE( | 341 static const char kFragmentShader[] = STRINGIZE( |
| 350 varying vec2 interp_tc; | 342 varying vec2 interp_tc; |
| 351 uniform sampler2D tex; | 343 uniform sampler2D tex; |
| 352 void main() { | 344 void main() { |
| 353 gl_FragColor = texture2D(tex, interp_tc); | 345 gl_FragColor = texture2D(tex, interp_tc); |
| 354 }); | 346 }); |
| 355 #endif | 347 #endif |
| 356 program_ = glCreateProgram(); | 348 program_ = glCreateProgram(); |
| 357 CreateShader( | 349 CreateShader( |
| 358 program_, GL_VERTEX_SHADER, kVertexShader, arraysize(kVertexShader)); | 350 program_, GL_VERTEX_SHADER, kVertexShader, arraysize(kVertexShader)); |
| 359 CreateShader(program_, | 351 CreateShader(program_, |
| 360 GL_FRAGMENT_SHADER, | 352 GL_FRAGMENT_SHADER, |
| 361 kFragmentShader, | 353 kFragmentShader, |
| 362 arraysize(kFragmentShader)); | 354 arraysize(kFragmentShader)); |
| 363 glLinkProgram(program_); | 355 glLinkProgram(program_); |
| 364 int result = GL_FALSE; | 356 int result = GL_FALSE; |
| 365 glGetProgramiv(program_, GL_LINK_STATUS, &result); | 357 glGetProgramiv(program_, GL_LINK_STATUS, &result); |
| 366 if (!result) { | 358 if (!result) { |
| 367 char log[4096]; | 359 char log[4096]; |
| 368 glGetShaderInfoLog(program_, arraysize(log), NULL, log); | 360 glGetShaderInfoLog(program_, arraysize(log), NULL, log); |
| 369 LOG(FATAL) << log; | 361 LOG(FATAL) << log; |
| 370 } | 362 } |
| 371 glUseProgram(program_); | 363 glUseProgram(program_); |
| 372 glDeleteProgram(program_); | 364 glDeleteProgram(program_); |
| 373 | 365 |
| 374 glUniform1i(glGetUniformLocation(program_, "tex_flip"), 0); | 366 glUniform1i(glGetUniformLocation(program_, "tex_flip"), 0); |
| 375 glUniform1i(glGetUniformLocation(program_, "tex"), 0); | 367 glUniform1i(glGetUniformLocation(program_, "tex"), 0); |
| 376 GLint tex_external = glGetUniformLocation(program_, "tex_external"); | |
| 377 if (tex_external != -1) { | |
| 378 glUniform1i(tex_external, 1); | |
| 379 } | |
| 380 int pos_location = glGetAttribLocation(program_, "in_pos"); | 368 int pos_location = glGetAttribLocation(program_, "in_pos"); |
| 381 glEnableVertexAttribArray(pos_location); | 369 glEnableVertexAttribArray(pos_location); |
| 382 glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, kVertices); | 370 glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, kVertices); |
| 383 int tc_location = glGetAttribLocation(program_, "in_tc"); | 371 int tc_location = glGetAttribLocation(program_, "in_tc"); |
| 384 glEnableVertexAttribArray(tc_location); | 372 glEnableVertexAttribArray(tc_location); |
| 385 glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, kTextureCoords); | 373 glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, kTextureCoords); |
| 386 done->Signal(); | 374 done->Signal(); |
| 387 } | 375 } |
| 388 | 376 |
| 389 void RenderingHelper::UnInitialize(base::WaitableEvent* done) { | 377 void RenderingHelper::UnInitialize(base::WaitableEvent* done) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 411 uint32 texture_target, | 399 uint32 texture_target, |
| 412 uint32* texture_id, | 400 uint32* texture_id, |
| 413 base::WaitableEvent* done) { | 401 base::WaitableEvent* done) { |
| 414 if (base::MessageLoop::current() != message_loop_) { | 402 if (base::MessageLoop::current() != message_loop_) { |
| 415 message_loop_->PostTask( | 403 message_loop_->PostTask( |
| 416 FROM_HERE, | 404 FROM_HERE, |
| 417 base::Bind(&RenderingHelper::CreateTexture, base::Unretained(this), | 405 base::Bind(&RenderingHelper::CreateTexture, base::Unretained(this), |
| 418 window_id, texture_target, texture_id, done)); | 406 window_id, texture_target, texture_id, done)); |
| 419 return; | 407 return; |
| 420 } | 408 } |
| 409 CHECK_EQ(static_cast<uint32>(GL_TEXTURE_2D), texture_target); |
| 421 MakeCurrent(window_id); | 410 MakeCurrent(window_id); |
| 422 glGenTextures(1, texture_id); | 411 glGenTextures(1, texture_id); |
| 423 glBindTexture(texture_target, *texture_id); | 412 glBindTexture(GL_TEXTURE_2D, *texture_id); |
| 424 int dimensions_id = window_id % frame_dimensions_.size(); | 413 int dimensions_id = window_id % frame_dimensions_.size(); |
| 425 if (texture_target == GL_TEXTURE_2D) { | 414 glTexImage2D(GL_TEXTURE_2D, |
| 426 glTexImage2D(GL_TEXTURE_2D, | 415 0, |
| 427 0, | 416 GL_RGBA, |
| 428 GL_RGBA, | 417 frame_dimensions_[dimensions_id].width(), |
| 429 frame_dimensions_[dimensions_id].width(), | 418 frame_dimensions_[dimensions_id].height(), |
| 430 frame_dimensions_[dimensions_id].height(), | 419 0, |
| 431 0, | 420 GL_RGBA, |
| 432 GL_RGBA, | 421 GL_UNSIGNED_BYTE, |
| 433 GL_UNSIGNED_BYTE, | 422 NULL); |
| 434 NULL); | 423 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 435 } | 424 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| 436 glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
| 437 glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
| 438 // OpenGLES2.0.25 section 3.8.2 requires CLAMP_TO_EDGE for NPOT textures. | 425 // OpenGLES2.0.25 section 3.8.2 requires CLAMP_TO_EDGE for NPOT textures. |
| 439 glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 426 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 440 glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 427 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 441 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); | 428 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); |
| 442 CHECK(texture_id_to_surface_index_.insert( | 429 CHECK(texture_id_to_surface_index_.insert( |
| 443 std::make_pair(*texture_id, window_id)).second); | 430 std::make_pair(*texture_id, window_id)).second); |
| 444 done->Signal(); | 431 done->Signal(); |
| 445 } | 432 } |
| 446 | 433 |
| 447 void RenderingHelper::RenderTexture(uint32 texture_target, uint32 texture_id) { | 434 void RenderingHelper::RenderTexture(uint32 texture_id) { |
| 448 CHECK_EQ(base::MessageLoop::current(), message_loop_); | 435 CHECK_EQ(base::MessageLoop::current(), message_loop_); |
| 449 size_t window_id = texture_id_to_surface_index_[texture_id]; | 436 size_t window_id = texture_id_to_surface_index_[texture_id]; |
| 450 MakeCurrent(window_id); | 437 MakeCurrent(window_id); |
| 451 | 438 |
| 452 int dimensions_id = window_id % window_dimensions_.size(); | 439 int dimensions_id = window_id % window_dimensions_.size(); |
| 453 int width = window_dimensions_[dimensions_id].width(); | 440 int width = window_dimensions_[dimensions_id].width(); |
| 454 int height = window_dimensions_[dimensions_id].height(); | 441 int height = window_dimensions_[dimensions_id].height(); |
| 455 | 442 |
| 456 if (render_as_thumbnails_) { | 443 if (render_as_thumbnails_) { |
| 457 glBindFramebufferEXT(GL_FRAMEBUFFER, thumbnails_fbo_id_); | 444 glBindFramebufferEXT(GL_FRAMEBUFFER, thumbnails_fbo_id_); |
| 458 const int thumbnails_in_row = | 445 const int thumbnails_in_row = |
| 459 thumbnails_fbo_size_.width() / thumbnail_size_.width(); | 446 thumbnails_fbo_size_.width() / thumbnail_size_.width(); |
| 460 const int thumbnails_in_column = | 447 const int thumbnails_in_column = |
| 461 thumbnails_fbo_size_.height() / thumbnail_size_.height(); | 448 thumbnails_fbo_size_.height() / thumbnail_size_.height(); |
| 462 const int row = (frame_count_ / thumbnails_in_row) % thumbnails_in_column; | 449 const int row = (frame_count_ / thumbnails_in_row) % thumbnails_in_column; |
| 463 const int col = frame_count_ % thumbnails_in_row; | 450 const int col = frame_count_ % thumbnails_in_row; |
| 464 const int x = col * thumbnail_size_.width(); | 451 const int x = col * thumbnail_size_.width(); |
| 465 const int y = row * thumbnail_size_.height(); | 452 const int y = row * thumbnail_size_.height(); |
| 466 | 453 |
| 467 glViewport(x, y, thumbnail_size_.width(), thumbnail_size_.height()); | 454 glViewport(x, y, thumbnail_size_.width(), thumbnail_size_.height()); |
| 468 glScissor(x, y, thumbnail_size_.width(), thumbnail_size_.height()); | 455 glScissor(x, y, thumbnail_size_.width(), thumbnail_size_.height()); |
| 469 glUniform1i(glGetUniformLocation(program_, "tex_flip"), 0); | 456 glUniform1i(glGetUniformLocation(program_, "tex_flip"), 0); |
| 470 } else { | 457 } else { |
| 471 glViewport(0, 0, width, height); | 458 glViewport(0, 0, width, height); |
| 472 glScissor(0, 0, width, height); | 459 glScissor(0, 0, width, height); |
| 473 glUniform1i(glGetUniformLocation(program_, "tex_flip"), 1); | 460 glUniform1i(glGetUniformLocation(program_, "tex_flip"), 1); |
| 474 } | 461 } |
| 475 | 462 |
| 476 // Unbound texture samplers default to (0, 0, 0, 1). Use this fact to switch | 463 glActiveTexture(GL_TEXTURE0); |
| 477 // between GL_TEXTURE_2D and GL_TEXTURE_EXTERNAL_OES as appopriate. | 464 glBindTexture(GL_TEXTURE_2D, texture_id); |
| 478 if (texture_target == GL_TEXTURE_2D) { | |
| 479 glActiveTexture(GL_TEXTURE0 + 0); | |
| 480 glBindTexture(GL_TEXTURE_2D, texture_id); | |
| 481 glActiveTexture(GL_TEXTURE0 + 1); | |
| 482 glBindTexture(texture_target, 0); | |
| 483 } else if (texture_target == GL_TEXTURE_EXTERNAL_OES) { | |
| 484 glActiveTexture(GL_TEXTURE0 + 0); | |
| 485 glBindTexture(GL_TEXTURE_2D, 0); | |
| 486 glActiveTexture(GL_TEXTURE0 + 1); | |
| 487 glBindTexture(texture_target, texture_id); | |
| 488 } | |
| 489 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | 465 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| 490 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); | 466 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); |
| 491 | 467 |
| 492 ++frame_count_; | 468 ++frame_count_; |
| 493 | 469 |
| 494 if (render_as_thumbnails_) { | 470 if (render_as_thumbnails_) { |
| 495 // Copy from FBO to screen | 471 // Copy from FBO to screen |
| 496 glUniform1i(glGetUniformLocation(program_, "tex_flip"), 1); | 472 glUniform1i(glGetUniformLocation(program_, "tex_flip"), 1); |
| 497 glBindFramebufferEXT(GL_FRAMEBUFFER, 0); | 473 glBindFramebufferEXT(GL_FRAMEBUFFER, 0); |
| 498 glViewport(0, 0, width, height); | 474 glViewport(0, 0, width, height); |
| 499 glScissor(0, 0, width, height); | 475 glScissor(0, 0, width, height); |
| 500 glActiveTexture(GL_TEXTURE0 + 0); | |
| 501 glBindTexture(GL_TEXTURE_2D, thumbnails_texture_id_); | 476 glBindTexture(GL_TEXTURE_2D, thumbnails_texture_id_); |
| 502 glActiveTexture(GL_TEXTURE0 + 1); | |
| 503 glBindTexture(texture_target, 0); | |
| 504 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | 477 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| 505 } | 478 } |
| 506 | 479 |
| 507 #if GL_VARIANT_GLX | 480 #if GL_VARIANT_GLX |
| 508 glXSwapBuffers(x_display_, x_windows_[window_id]); | 481 glXSwapBuffers(x_display_, x_windows_[window_id]); |
| 509 #else // EGL | 482 #else // EGL |
| 510 eglSwapBuffers(gl_display_, gl_surfaces_[window_id]); | 483 eglSwapBuffers(gl_display_, gl_surfaces_[window_id]); |
| 511 CHECK_EQ(static_cast<int>(eglGetError()), EGL_SUCCESS); | 484 CHECK_EQ(static_cast<int>(eglGetError()), EGL_SUCCESS); |
| 512 #endif | 485 #endif |
| 513 } | 486 } |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 572 glBindFramebufferEXT(GL_FRAMEBUFFER, thumbnails_fbo_id_); | 545 glBindFramebufferEXT(GL_FRAMEBUFFER, thumbnails_fbo_id_); |
| 573 glPixelStorei(GL_PACK_ALIGNMENT, 1); | 546 glPixelStorei(GL_PACK_ALIGNMENT, 1); |
| 574 // We can only count on GL_RGBA/GL_UNSIGNED_BYTE support. | 547 // We can only count on GL_RGBA/GL_UNSIGNED_BYTE support. |
| 575 glReadPixels(0, | 548 glReadPixels(0, |
| 576 0, | 549 0, |
| 577 thumbnails_fbo_size_.width(), | 550 thumbnails_fbo_size_.width(), |
| 578 thumbnails_fbo_size_.height(), | 551 thumbnails_fbo_size_.height(), |
| 579 GL_RGBA, | 552 GL_RGBA, |
| 580 GL_UNSIGNED_BYTE, | 553 GL_UNSIGNED_BYTE, |
| 581 &rgba[0]); | 554 &rgba[0]); |
| 582 glBindFramebufferEXT(GL_FRAMEBUFFER, 0); | |
| 583 rgb->resize(num_pixels * 3); | 555 rgb->resize(num_pixels * 3); |
| 584 // Drop the alpha channel, but check as we go that it is all 0xff. | 556 // Drop the alpha channel, but check as we go that it is all 0xff. |
| 585 bool solid = true; | 557 bool solid = true; |
| 586 unsigned char* rgb_ptr = &((*rgb)[0]); | 558 unsigned char* rgb_ptr = &((*rgb)[0]); |
| 587 unsigned char* rgba_ptr = &rgba[0]; | 559 unsigned char* rgba_ptr = &rgba[0]; |
| 588 for (size_t i = 0; i < num_pixels; ++i) { | 560 for (size_t i = 0; i < num_pixels; ++i) { |
| 589 *rgb_ptr++ = *rgba_ptr++; | 561 *rgb_ptr++ = *rgba_ptr++; |
| 590 *rgb_ptr++ = *rgba_ptr++; | 562 *rgb_ptr++ = *rgba_ptr++; |
| 591 *rgb_ptr++ = *rgba_ptr++; | 563 *rgb_ptr++ = *rgba_ptr++; |
| 592 solid = solid && (*rgba_ptr == 0xff); | 564 solid = solid && (*rgba_ptr == 0xff); |
| 593 rgba_ptr++; | 565 rgba_ptr++; |
| 594 } | 566 } |
| 595 *alpha_solid = solid; | 567 *alpha_solid = solid; |
| 596 | 568 |
| 597 done->Signal(); | 569 done->Signal(); |
| 598 } | 570 } |
| 599 | 571 |
| 600 } // namespace content | 572 } // namespace content |
| OLD | NEW |