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 |