| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium OS 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 "window_manager/compositor/gl/opengl_visitor.h" | 5 #include "window_manager/compositor/gl/opengl_visitor.h" |
| 6 | 6 |
| 7 #include <sys/time.h> | 7 #include <sys/time.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <ctime> | 10 #include <ctime> |
| (...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 gl_interface_->Finish(); | 389 gl_interface_->Finish(); |
| 390 // Make sure the vertex buffer is deleted. | 390 // Make sure the vertex buffer is deleted. |
| 391 quad_drawing_data_.reset(NULL); | 391 quad_drawing_data_.reset(NULL); |
| 392 CHECK_GL_ERROR(gl_interface_); | 392 CHECK_GL_ERROR(gl_interface_); |
| 393 gl_interface_->MakeGlxCurrent(0, 0); | 393 gl_interface_->MakeGlxCurrent(0, 0); |
| 394 if (context_) { | 394 if (context_) { |
| 395 gl_interface_->DestroyGlxContext(context_); | 395 gl_interface_->DestroyGlxContext(context_); |
| 396 } | 396 } |
| 397 } | 397 } |
| 398 | 398 |
| 399 void OpenGlDrawVisitor::BindImage(const ImageContainer* container, | 399 void OpenGlDrawVisitor::BindImage(const ImageContainer& container, |
| 400 RealCompositor::ImageActor* actor) { | 400 RealCompositor::ImageActor* actor) { |
| 401 GLenum pixel_data_format = 0; | 401 GLenum pixel_data_format = 0; |
| 402 switch (container->format()) { | 402 switch (container.format()) { |
| 403 case IMAGE_FORMAT_RGBA_32: // fallthrough | 403 case IMAGE_FORMAT_RGBA_32: // fallthrough |
| 404 case IMAGE_FORMAT_RGBX_32: | 404 case IMAGE_FORMAT_RGBX_32: |
| 405 pixel_data_format = GL_RGBA; | 405 pixel_data_format = GL_RGBA; |
| 406 break; | 406 break; |
| 407 case IMAGE_FORMAT_BGRA_32: // fallthrough | 407 case IMAGE_FORMAT_BGRA_32: // fallthrough |
| 408 case IMAGE_FORMAT_BGRX_32: | 408 case IMAGE_FORMAT_BGRX_32: |
| 409 pixel_data_format = GL_BGRA; | 409 pixel_data_format = GL_BGRA; |
| 410 break; | 410 break; |
| 411 default: | 411 default: |
| 412 NOTREACHED() << "Unhandled image container data format " | 412 NOTREACHED() << "Unhandled image container data format " |
| 413 << container->format(); | 413 << container.format(); |
| 414 } | 414 } |
| 415 | 415 |
| 416 // Create an OpenGL texture with the loaded image data. | 416 // Create an OpenGL texture with the loaded image data. |
| 417 GLuint new_texture = 0; | 417 GLuint new_texture = 0; |
| 418 gl_interface_->Enable(GL_TEXTURE_2D); | 418 gl_interface_->Enable(GL_TEXTURE_2D); |
| 419 gl_interface_->GenTextures(1, &new_texture); | 419 gl_interface_->GenTextures(1, &new_texture); |
| 420 gl_interface_->BindTexture(GL_TEXTURE_2D, new_texture); | 420 gl_interface_->BindTexture(GL_TEXTURE_2D, new_texture); |
| 421 gl_interface_->TexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | 421 gl_interface_->TexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); |
| 422 gl_interface_->TexParameterf(GL_TEXTURE_2D, | 422 gl_interface_->TexParameterf(GL_TEXTURE_2D, |
| 423 GL_TEXTURE_MIN_FILTER, | 423 GL_TEXTURE_MIN_FILTER, |
| 424 GL_LINEAR); | 424 GL_LINEAR); |
| 425 gl_interface_->TexParameterf(GL_TEXTURE_2D, | 425 gl_interface_->TexParameterf(GL_TEXTURE_2D, |
| 426 GL_TEXTURE_MAG_FILTER, | 426 GL_TEXTURE_MAG_FILTER, |
| 427 GL_LINEAR); | 427 GL_LINEAR); |
| 428 gl_interface_->TexParameterf(GL_TEXTURE_2D, | 428 gl_interface_->TexParameterf(GL_TEXTURE_2D, |
| 429 GL_TEXTURE_WRAP_S, | 429 GL_TEXTURE_WRAP_S, |
| 430 GL_CLAMP_TO_EDGE); | 430 GL_CLAMP_TO_EDGE); |
| 431 gl_interface_->TexParameterf(GL_TEXTURE_2D, | 431 gl_interface_->TexParameterf(GL_TEXTURE_2D, |
| 432 GL_TEXTURE_WRAP_T, | 432 GL_TEXTURE_WRAP_T, |
| 433 GL_CLAMP_TO_EDGE); | 433 GL_CLAMP_TO_EDGE); |
| 434 gl_interface_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, | 434 gl_interface_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, |
| 435 container->width(), container->height(), | 435 container.width(), container.height(), |
| 436 0, pixel_data_format, GL_UNSIGNED_BYTE, | 436 0, pixel_data_format, GL_UNSIGNED_BYTE, |
| 437 container->data()); | 437 container.data()); |
| 438 CHECK_GL_ERROR(gl_interface_); | 438 CHECK_GL_ERROR(gl_interface_); |
| 439 scoped_ptr<OpenGlTextureData> data(new OpenGlTextureData(gl_interface_)); | 439 scoped_ptr<OpenGlTextureData> data(new OpenGlTextureData(gl_interface_)); |
| 440 data->SetTexture(new_texture); | 440 data->SetTexture(new_texture); |
| 441 data->set_has_alpha(ImageFormatUsesAlpha(container->format())); | 441 data->set_has_alpha(ImageFormatUsesAlpha(container.format())); |
| 442 actor->set_texture_data(data.release()); | 442 actor->set_texture_data(data.release()); |
| 443 } | 443 } |
| 444 | 444 |
| 445 void OpenGlDrawVisitor::VisitImage(RealCompositor::ImageActor* actor) { | |
| 446 if (!actor->IsVisible()) | |
| 447 return; | |
| 448 | |
| 449 PROFILER_MARKER_BEGIN(VisitImage); | |
| 450 | |
| 451 // All ImageActors are also QuadActors, and so we let the | |
| 452 // QuadActor do all the actual drawing. | |
| 453 VisitQuad(actor); | |
| 454 PROFILER_MARKER_END(VisitImage); | |
| 455 } | |
| 456 | |
| 457 void OpenGlDrawVisitor::VisitTexturePixmap( | |
| 458 RealCompositor::TexturePixmapActor* actor) { | |
| 459 if (!actor->IsVisible()) | |
| 460 return; | |
| 461 | |
| 462 PROFILER_MARKER_BEGIN(VisitTexturePixmap); | |
| 463 | |
| 464 // Make sure there's a bound texture. | |
| 465 if (!actor->texture_data()) { | |
| 466 if (!actor->pixmap()) { | |
| 467 PROFILER_MARKER_END(VisitTexturePixmap); | |
| 468 return; | |
| 469 } | |
| 470 | |
| 471 scoped_ptr<OpenGlPixmapData> data(new OpenGlPixmapData(this)); | |
| 472 if (!data->Init(actor)) { | |
| 473 PROFILER_MARKER_END(VisitTexturePixmap); | |
| 474 return; | |
| 475 } | |
| 476 data->set_has_alpha(!actor->pixmap_is_opaque()); | |
| 477 actor->set_texture_data(data.release()); | |
| 478 } | |
| 479 | |
| 480 // All texture pixmaps are also QuadActors, and so we let the | |
| 481 // QuadActor do all the actual drawing. | |
| 482 VisitQuad(actor); | |
| 483 PROFILER_MARKER_END(VisitTexturePixmap); | |
| 484 } | |
| 485 | |
| 486 void OpenGlDrawVisitor::VisitQuad(RealCompositor::QuadActor* actor) { | |
| 487 if (!actor->IsVisible()) | |
| 488 return; | |
| 489 | |
| 490 #ifdef EXTRA_LOGGING | |
| 491 DLOG(INFO) << "Drawing quad " << actor->name() << "."; | |
| 492 #endif | |
| 493 PROFILER_DYNAMIC_MARKER_BEGIN(actor->name().c_str()); | |
| 494 | |
| 495 // Calculate the vertex colors, taking into account the actor color, | |
| 496 // opacity and the dimming gradient. | |
| 497 float actor_opacity = actor->is_opaque() ? 1.0f : | |
| 498 actor->opacity() * ancestor_opacity_; | |
| 499 float dimmed_transparency_begin = 1.f - actor->dimmed_opacity_begin(); | |
| 500 float dimmed_transparency_end = 1.f - actor->dimmed_opacity_end(); | |
| 501 float red = actor->color().red; | |
| 502 float green = actor->color().green; | |
| 503 float blue = actor->color().blue; | |
| 504 DCHECK_LE(actor_opacity, 1.f); | |
| 505 DCHECK_GE(actor_opacity, 0.f); | |
| 506 DCHECK_LE(dimmed_transparency_begin, 1.f); | |
| 507 DCHECK_GE(dimmed_transparency_begin, 0.f); | |
| 508 DCHECK_LE(dimmed_transparency_end, 1.f); | |
| 509 DCHECK_GE(dimmed_transparency_end, 0.f); | |
| 510 DCHECK_LE(red, 1.f); | |
| 511 DCHECK_GE(red, 0.f); | |
| 512 DCHECK_LE(green, 1.f); | |
| 513 DCHECK_GE(green, 0.f); | |
| 514 DCHECK_LE(blue, 1.f); | |
| 515 DCHECK_GE(blue, 0.f); | |
| 516 | |
| 517 if (state_cache_.ColorStateChanged(actor_opacity, | |
| 518 dimmed_transparency_begin, | |
| 519 dimmed_transparency_end, | |
| 520 red, green, blue)) { | |
| 521 // Scale the vertex colors on the right by the transparency, since | |
| 522 // we want it to fade to black as transparency of the dimming | |
| 523 // overlay goes to zero. (note that the dimming is not *really* an | |
| 524 // overlay -- it's just multiplied in here to simulate that). | |
| 525 float dim_red_begin = red * dimmed_transparency_begin; | |
| 526 float dim_green_begin = green * dimmed_transparency_begin; | |
| 527 float dim_blue_begin = blue * dimmed_transparency_begin; | |
| 528 float dim_red_end = red * dimmed_transparency_end; | |
| 529 float dim_green_end = green * dimmed_transparency_end; | |
| 530 float dim_blue_end = blue * dimmed_transparency_end; | |
| 531 | |
| 532 quad_drawing_data_->set_vertex_color( | |
| 533 0, dim_red_begin, dim_green_begin, dim_blue_begin, actor_opacity); | |
| 534 quad_drawing_data_->set_vertex_color( | |
| 535 1, dim_red_begin, dim_green_begin, dim_blue_begin, actor_opacity); | |
| 536 quad_drawing_data_->set_vertex_color( | |
| 537 2, dim_red_end, dim_green_end, dim_blue_end, actor_opacity); | |
| 538 quad_drawing_data_->set_vertex_color( | |
| 539 3, dim_red_end, dim_green_end, dim_blue_end, actor_opacity); | |
| 540 | |
| 541 gl_interface_->EnableClientState(GL_COLOR_ARRAY); | |
| 542 // Have to un-bind the array buffer to set the color pointer so that | |
| 543 // it uses the color buffer instead of the vertex buffer memory. | |
| 544 gl_interface_->BindBuffer(GL_ARRAY_BUFFER, 0); | |
| 545 gl_interface_->ColorPointer(4, GL_FLOAT, 0, | |
| 546 quad_drawing_data_->color_buffer()); | |
| 547 } | |
| 548 | |
| 549 gl_interface_->BindBuffer(GL_ARRAY_BUFFER, | |
| 550 quad_drawing_data_->vertex_buffer()); | |
| 551 CHECK_GL_ERROR(gl_interface_); | |
| 552 | |
| 553 // Find out if this quad has pixmap or texture data to bind. | |
| 554 if (actor->texture_data()) { | |
| 555 // Actor has a texture to bind. | |
| 556 gl_interface_->Enable(GL_TEXTURE_2D); | |
| 557 gl_interface_->BindTexture(GL_TEXTURE_2D, | |
| 558 actor->texture_data()->texture()); | |
| 559 } else { | |
| 560 // Actor has no texture. | |
| 561 gl_interface_->Disable(GL_TEXTURE_2D); | |
| 562 } | |
| 563 | |
| 564 #ifdef EXTRA_LOGGING | |
| 565 DLOG(INFO) << " at: (" << actor->x() << ", " << actor->y() | |
| 566 << ", " << actor->z() << ") with scale: (" | |
| 567 << actor->scale_x() << ", " << actor->scale_y() << ") at size (" | |
| 568 << actor->width() << "x" << actor->height() | |
| 569 << ") and opacity " << actor_opacity; | |
| 570 #endif | |
| 571 | |
| 572 gl_interface_->PushMatrix(); | |
| 573 // operator[] in Matrix4 returns by value in const version. | |
| 574 Matrix4 model_view = actor->model_view(); | |
| 575 gl_interface_->LoadMatrixf(&model_view[0][0]); | |
| 576 gl_interface_->DrawArrays(GL_TRIANGLE_STRIP, 0, 4); | |
| 577 gl_interface_->PopMatrix(); | |
| 578 CHECK_GL_ERROR(gl_interface_); | |
| 579 PROFILER_DYNAMIC_MARKER_END(); | |
| 580 } | |
| 581 | |
| 582 void OpenGlDrawVisitor::DrawNeedle() { | 445 void OpenGlDrawVisitor::DrawNeedle() { |
| 583 PROFILER_MARKER_BEGIN(DrawNeedle); | 446 PROFILER_MARKER_BEGIN(DrawNeedle); |
| 584 gl_interface_->BindBuffer(GL_ARRAY_BUFFER, | 447 gl_interface_->BindBuffer(GL_ARRAY_BUFFER, |
| 585 quad_drawing_data_->vertex_buffer()); | 448 quad_drawing_data_->vertex_buffer()); |
| 586 gl_interface_->EnableClientState(GL_VERTEX_ARRAY); | 449 gl_interface_->EnableClientState(GL_VERTEX_ARRAY); |
| 587 gl_interface_->VertexPointer(2, GL_FLOAT, 0, 0); | 450 gl_interface_->VertexPointer(2, GL_FLOAT, 0, 0); |
| 588 gl_interface_->DisableClientState(GL_TEXTURE_COORD_ARRAY); | 451 gl_interface_->DisableClientState(GL_TEXTURE_COORD_ARRAY); |
| 589 gl_interface_->DisableClientState(GL_COLOR_ARRAY); | 452 gl_interface_->DisableClientState(GL_COLOR_ARRAY); |
| 590 gl_interface_->Disable(GL_TEXTURE_2D); | 453 gl_interface_->Disable(GL_TEXTURE_2D); |
| 591 gl_interface_->PushMatrix(); | 454 gl_interface_->PushMatrix(); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 724 else | 587 else |
| 725 gl_interface_->Enable(GL_BLEND); | 588 gl_interface_->Enable(GL_BLEND); |
| 726 child->Accept(this); | 589 child->Accept(this); |
| 727 CHECK_GL_ERROR(gl_interface_); | 590 CHECK_GL_ERROR(gl_interface_); |
| 728 } | 591 } |
| 729 | 592 |
| 730 // Reset ancestor opacity. | 593 // Reset ancestor opacity. |
| 731 ancestor_opacity_ = original_opacity; | 594 ancestor_opacity_ = original_opacity; |
| 732 } | 595 } |
| 733 | 596 |
| 597 void OpenGlDrawVisitor::VisitImage(RealCompositor::ImageActor* actor) { |
| 598 if (!actor->IsVisible()) |
| 599 return; |
| 600 |
| 601 PROFILER_MARKER_BEGIN(VisitImage); |
| 602 |
| 603 // All ImageActors are also QuadActors, and so we let the |
| 604 // QuadActor do all the actual drawing. |
| 605 VisitQuad(actor); |
| 606 PROFILER_MARKER_END(VisitImage); |
| 607 } |
| 608 |
| 609 void OpenGlDrawVisitor::VisitTexturePixmap( |
| 610 RealCompositor::TexturePixmapActor* actor) { |
| 611 if (!actor->IsVisible()) |
| 612 return; |
| 613 |
| 614 PROFILER_MARKER_BEGIN(VisitTexturePixmap); |
| 615 |
| 616 // Make sure there's a bound texture. |
| 617 if (!actor->texture_data()) { |
| 618 if (!actor->pixmap()) { |
| 619 PROFILER_MARKER_END(VisitTexturePixmap); |
| 620 return; |
| 621 } |
| 622 |
| 623 scoped_ptr<OpenGlPixmapData> data(new OpenGlPixmapData(this)); |
| 624 if (!data->Init(actor)) { |
| 625 PROFILER_MARKER_END(VisitTexturePixmap); |
| 626 return; |
| 627 } |
| 628 data->set_has_alpha(!actor->pixmap_is_opaque()); |
| 629 actor->set_texture_data(data.release()); |
| 630 } |
| 631 |
| 632 // All texture pixmaps are also QuadActors, and so we let the |
| 633 // QuadActor do all the actual drawing. |
| 634 VisitQuad(actor); |
| 635 PROFILER_MARKER_END(VisitTexturePixmap); |
| 636 } |
| 637 |
| 638 void OpenGlDrawVisitor::VisitQuad(RealCompositor::QuadActor* actor) { |
| 639 if (!actor->IsVisible()) |
| 640 return; |
| 641 |
| 642 #ifdef EXTRA_LOGGING |
| 643 DLOG(INFO) << "Drawing quad " << actor->name() << "."; |
| 644 #endif |
| 645 PROFILER_DYNAMIC_MARKER_BEGIN(actor->name().c_str()); |
| 646 |
| 647 // Calculate the vertex colors, taking into account the actor color, |
| 648 // opacity and the dimming gradient. |
| 649 float actor_opacity = actor->is_opaque() ? 1.0f : |
| 650 actor->opacity() * ancestor_opacity_; |
| 651 float dimmed_transparency_begin = 1.f - actor->dimmed_opacity_begin(); |
| 652 float dimmed_transparency_end = 1.f - actor->dimmed_opacity_end(); |
| 653 float red = actor->color().red; |
| 654 float green = actor->color().green; |
| 655 float blue = actor->color().blue; |
| 656 DCHECK_LE(actor_opacity, 1.f); |
| 657 DCHECK_GE(actor_opacity, 0.f); |
| 658 DCHECK_LE(dimmed_transparency_begin, 1.f); |
| 659 DCHECK_GE(dimmed_transparency_begin, 0.f); |
| 660 DCHECK_LE(dimmed_transparency_end, 1.f); |
| 661 DCHECK_GE(dimmed_transparency_end, 0.f); |
| 662 DCHECK_LE(red, 1.f); |
| 663 DCHECK_GE(red, 0.f); |
| 664 DCHECK_LE(green, 1.f); |
| 665 DCHECK_GE(green, 0.f); |
| 666 DCHECK_LE(blue, 1.f); |
| 667 DCHECK_GE(blue, 0.f); |
| 668 |
| 669 if (state_cache_.ColorStateChanged(actor_opacity, |
| 670 dimmed_transparency_begin, |
| 671 dimmed_transparency_end, |
| 672 red, green, blue)) { |
| 673 // Scale the vertex colors on the right by the transparency, since |
| 674 // we want it to fade to black as transparency of the dimming |
| 675 // overlay goes to zero. (note that the dimming is not *really* an |
| 676 // overlay -- it's just multiplied in here to simulate that). |
| 677 float dim_red_begin = red * dimmed_transparency_begin; |
| 678 float dim_green_begin = green * dimmed_transparency_begin; |
| 679 float dim_blue_begin = blue * dimmed_transparency_begin; |
| 680 float dim_red_end = red * dimmed_transparency_end; |
| 681 float dim_green_end = green * dimmed_transparency_end; |
| 682 float dim_blue_end = blue * dimmed_transparency_end; |
| 683 |
| 684 quad_drawing_data_->set_vertex_color( |
| 685 0, dim_red_begin, dim_green_begin, dim_blue_begin, actor_opacity); |
| 686 quad_drawing_data_->set_vertex_color( |
| 687 1, dim_red_begin, dim_green_begin, dim_blue_begin, actor_opacity); |
| 688 quad_drawing_data_->set_vertex_color( |
| 689 2, dim_red_end, dim_green_end, dim_blue_end, actor_opacity); |
| 690 quad_drawing_data_->set_vertex_color( |
| 691 3, dim_red_end, dim_green_end, dim_blue_end, actor_opacity); |
| 692 |
| 693 gl_interface_->EnableClientState(GL_COLOR_ARRAY); |
| 694 // Have to un-bind the array buffer to set the color pointer so that |
| 695 // it uses the color buffer instead of the vertex buffer memory. |
| 696 gl_interface_->BindBuffer(GL_ARRAY_BUFFER, 0); |
| 697 gl_interface_->ColorPointer(4, GL_FLOAT, 0, |
| 698 quad_drawing_data_->color_buffer()); |
| 699 } |
| 700 |
| 701 gl_interface_->BindBuffer(GL_ARRAY_BUFFER, |
| 702 quad_drawing_data_->vertex_buffer()); |
| 703 CHECK_GL_ERROR(gl_interface_); |
| 704 |
| 705 // Find out if this quad has pixmap or texture data to bind. |
| 706 if (actor->texture_data()) { |
| 707 // Actor has a texture to bind. |
| 708 gl_interface_->Enable(GL_TEXTURE_2D); |
| 709 gl_interface_->BindTexture(GL_TEXTURE_2D, |
| 710 actor->texture_data()->texture()); |
| 711 } else { |
| 712 // Actor has no texture. |
| 713 gl_interface_->Disable(GL_TEXTURE_2D); |
| 714 } |
| 715 |
| 716 #ifdef EXTRA_LOGGING |
| 717 DLOG(INFO) << " at: (" << actor->x() << ", " << actor->y() |
| 718 << ", " << actor->z() << ") with scale: (" |
| 719 << actor->scale_x() << ", " << actor->scale_y() << ") at size (" |
| 720 << actor->width() << "x" << actor->height() |
| 721 << ") and opacity " << actor_opacity; |
| 722 #endif |
| 723 |
| 724 gl_interface_->PushMatrix(); |
| 725 // operator[] in Matrix4 returns by value in const version. |
| 726 Matrix4 model_view = actor->model_view(); |
| 727 gl_interface_->LoadMatrixf(&model_view[0][0]); |
| 728 gl_interface_->DrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| 729 gl_interface_->PopMatrix(); |
| 730 CHECK_GL_ERROR(gl_interface_); |
| 731 PROFILER_DYNAMIC_MARKER_END(); |
| 732 } |
| 733 |
| 734 } // namespace window_manager | 734 } // namespace window_manager |
| OLD | NEW |