OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h" | 5 #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 | 10 |
(...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
610 source_y, source_width, source_height); | 610 source_y, source_width, source_height); |
611 } | 611 } |
612 | 612 |
613 decoder->RestoreTextureState(source_id); | 613 decoder->RestoreTextureState(source_id); |
614 decoder->RestoreTextureState(dest_id); | 614 decoder->RestoreTextureState(dest_id); |
615 decoder->RestoreTextureUnitBindings(0); | 615 decoder->RestoreTextureUnitBindings(0); |
616 decoder->RestoreActiveTexture(); | 616 decoder->RestoreActiveTexture(); |
617 decoder->RestoreFramebufferBindings(); | 617 decoder->RestoreFramebufferBindings(); |
618 } | 618 } |
619 | 619 |
620 // Convert RGBA/UNSIGNED_BYTE source to RGB/UNSIGNED_BYTE destination. | |
621 void convertToRGB(const uint8_t* source, | |
622 uint8_t* destination, | |
623 unsigned length) { | |
624 for (unsigned i = 0; i < length; ++i) { | |
625 destination[0] = source[0]; | |
626 destination[1] = source[1]; | |
627 destination[2] = source[2]; | |
628 source += 4; | |
629 destination += 3; | |
630 } | |
631 } | |
632 | |
633 // Convert RGBA/UNSIGNED_BYTE source to RGB/FLOAT destination. | |
634 void convertToRGBFloat(const uint8_t* source, | |
635 float* destination, | |
636 unsigned length) { | |
637 const float scaleFactor = 1.0f / 255.0f; | |
638 for (unsigned i = 0; i < length; ++i) { | |
639 destination[0] = source[0] * scaleFactor; | |
640 destination[1] = source[1] * scaleFactor; | |
641 destination[2] = source[2] * scaleFactor; | |
642 source += 4; | |
643 destination += 3; | |
644 } | |
645 } | |
646 | |
647 void DoReadbackAndTexImage2D(const gpu::gles2::GLES2Decoder* decoder, | |
648 GLenum source_target, | |
649 GLuint source_id, | |
650 GLint source_level, | |
651 GLenum dest_target, | |
652 GLuint dest_id, | |
653 GLint dest_level, | |
654 GLenum dest_internal_format, | |
655 GLsizei width, | |
656 GLsizei height, | |
657 GLuint framebuffer) { | |
658 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), source_target); | |
659 GLenum dest_binding_target = | |
660 gpu::gles2::GLES2Util::GLFaceTargetToTextureTarget(dest_target); | |
661 DCHECK(dest_binding_target == GL_TEXTURE_2D || | |
662 dest_binding_target == GL_TEXTURE_CUBE_MAP); | |
663 DCHECK(source_level == 0 || decoder->GetFeatureInfo()->IsES3Capable()); | |
664 if (BindFramebufferTexture2D(source_target, source_id, source_level, | |
665 framebuffer)) { | |
666 std::unique_ptr<uint8_t[]> buf(new uint8_t[width * height * 4]); | |
667 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf.get()); | |
Zhenyao Mo
2017/03/20 17:05:40
It would be really beneficial to explore the path
qiankun
2017/03/21 08:47:13
This is a good suggestion. Thanks! I did experimen
qiankun
2017/03/29 09:00:10
I did some experiments by running src/third_party/
| |
668 glBindTexture(dest_binding_target, dest_id); | |
669 glTexParameterf(dest_binding_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
670 glTexParameterf(dest_binding_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
671 glTexParameteri(dest_binding_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
672 glTexParameteri(dest_binding_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
673 GLenum format = GL_RGBA; | |
674 GLenum type = GL_UNSIGNED_BYTE; | |
675 switch (dest_internal_format) { | |
676 case GL_RGB9_E5: { | |
677 format = GL_RGB; | |
678 type = GL_FLOAT; | |
679 std::unique_ptr<float[]> data(new float[width * height * 3]); | |
680 convertToRGBFloat(buf.get(), data.get(), width * height); | |
681 glTexImage2D(dest_target, dest_level, dest_internal_format, width, | |
682 height, 0, format, type, data.get()); | |
683 break; | |
684 } | |
685 case GL_RGB5_A1: | |
686 glTexImage2D(dest_target, dest_level, dest_internal_format, width, | |
687 height, 0, format, type, buf.get()); | |
688 break; | |
689 case GL_SRGB_EXT: | |
690 case GL_SRGB8: { | |
691 format = GL_RGB; | |
692 std::unique_ptr<uint8_t[]> data(new uint8_t[width * height * 3]); | |
693 convertToRGB(buf.get(), data.get(), width * height); | |
694 glTexImage2D(dest_target, dest_level, dest_internal_format, width, | |
695 height, 0, format, type, data.get()); | |
696 break; | |
697 } | |
698 case GL_SRGB_ALPHA_EXT: | |
699 case GL_SRGB8_ALPHA8: | |
700 glTexImage2D(dest_target, dest_level, dest_internal_format, width, | |
701 height, 0, format, type, buf.get()); | |
702 break; | |
703 default: | |
704 NOTREACHED(); | |
705 break; | |
706 } | |
707 } | |
708 | |
709 decoder->RestoreTextureState(source_id); | |
710 decoder->RestoreTextureState(dest_id); | |
711 decoder->RestoreTextureUnitBindings(0); | |
712 decoder->RestoreActiveTexture(); | |
713 decoder->RestoreFramebufferBindings(); | |
714 } | |
715 | |
716 void DoReadbackAndTexSubImage2D(const gpu::gles2::GLES2Decoder* decoder, | |
717 GLenum source_target, | |
718 GLuint source_id, | |
719 GLint source_level, | |
720 GLenum dest_target, | |
721 GLuint dest_id, | |
722 GLint dest_level, | |
723 GLenum dest_internal_format, | |
724 GLint xoffset, | |
725 GLint yoffset, | |
726 GLsizei width, | |
727 GLsizei height, | |
728 GLuint framebuffer) { | |
729 DCHECK(source_target == GL_TEXTURE_2D || | |
730 source_target == GL_TEXTURE_RECTANGLE_ARB); | |
731 GLenum dest_binding_target = | |
732 gpu::gles2::GLES2Util::GLFaceTargetToTextureTarget(dest_target); | |
733 DCHECK(dest_binding_target == GL_TEXTURE_2D || | |
734 dest_binding_target == GL_TEXTURE_CUBE_MAP); | |
735 DCHECK(source_level == 0 || decoder->GetFeatureInfo()->IsES3Capable()); | |
736 if (BindFramebufferTexture2D(source_target, source_id, source_level, | |
737 framebuffer)) { | |
738 std::unique_ptr<uint8_t[]> buf(new uint8_t[width * height * 4]); | |
739 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf.get()); | |
740 glBindTexture(dest_binding_target, dest_id); | |
741 glTexParameterf(dest_binding_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
742 glTexParameterf(dest_binding_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
743 glTexParameteri(dest_binding_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
744 glTexParameteri(dest_binding_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
745 GLenum format = GL_RGBA; | |
746 GLenum type = GL_UNSIGNED_BYTE; | |
747 switch (dest_internal_format) { | |
748 case GL_RGB9_E5: { | |
749 format = GL_RGB; | |
750 type = GL_FLOAT; | |
751 std::unique_ptr<float[]> data(new float[width * height * 3]); | |
752 convertToRGBFloat(buf.get(), data.get(), width * height); | |
753 glTexSubImage2D(dest_target, dest_level, xoffset, yoffset, width, | |
754 height, format, type, data.get()); | |
755 break; | |
756 } | |
757 case GL_RGB5_A1: | |
758 glTexSubImage2D(dest_target, dest_level, xoffset, yoffset, width, | |
759 height, format, type, buf.get()); | |
760 break; | |
761 case GL_SRGB_EXT: | |
762 case GL_SRGB8: { | |
763 format = GL_RGB; | |
764 std::unique_ptr<uint8_t[]> data(new uint8_t[width * height * 3]); | |
765 convertToRGB(buf.get(), data.get(), width * height); | |
766 glTexSubImage2D(dest_target, dest_level, xoffset, yoffset, width, | |
767 height, format, type, data.get()); | |
768 break; | |
769 } | |
770 case GL_SRGB_ALPHA_EXT: | |
771 case GL_SRGB8_ALPHA8: | |
772 glTexSubImage2D(dest_target, dest_level, xoffset, yoffset, width, | |
773 height, format, type, buf.get()); | |
774 break; | |
775 default: | |
776 NOTREACHED(); | |
777 break; | |
778 } | |
779 } | |
780 | |
781 decoder->RestoreTextureState(source_id); | |
782 decoder->RestoreTextureState(dest_id); | |
783 decoder->RestoreTextureUnitBindings(0); | |
784 decoder->RestoreActiveTexture(); | |
785 decoder->RestoreFramebufferBindings(); | |
786 } | |
787 | |
620 } // namespace | 788 } // namespace |
621 | 789 |
622 namespace gpu { | 790 namespace gpu { |
623 namespace gles2 { | 791 namespace gles2 { |
624 | 792 |
625 CopyTextureCHROMIUMResourceManager::CopyTextureCHROMIUMResourceManager() | 793 CopyTextureCHROMIUMResourceManager::CopyTextureCHROMIUMResourceManager() |
626 : initialized_(false), | 794 : initialized_(false), |
627 nv_egl_stream_consumer_external_(false), | 795 nv_egl_stream_consumer_external_(false), |
628 vertex_shaders_(kNumVertexShaders, 0u), | 796 vertex_shaders_(kNumVertexShaders, 0u), |
629 fragment_shaders_(kNumFragmentShaders, 0u), | 797 fragment_shaders_(kNumFragmentShaders, 0u), |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
728 width, height, framebuffer_); | 896 width, height, framebuffer_); |
729 return; | 897 return; |
730 } | 898 } |
731 | 899 |
732 // Draw to level 0 of an intermediate GL_TEXTURE_2D texture. | 900 // Draw to level 0 of an intermediate GL_TEXTURE_2D texture. |
733 GLuint dest_texture = dest_id; | 901 GLuint dest_texture = dest_id; |
734 GLuint intermediate_texture = 0; | 902 GLuint intermediate_texture = 0; |
735 GLint original_dest_level = dest_level; | 903 GLint original_dest_level = dest_level; |
736 GLenum original_dest_target = dest_target; | 904 GLenum original_dest_target = dest_target; |
737 GLenum original_internal_format = dest_internal_format; | 905 GLenum original_internal_format = dest_internal_format; |
738 if (method == DRAW_AND_COPY) { | 906 if (method == DRAW_AND_COPY || method == DRAW_AND_READBACK) { |
739 GLenum adjusted_internal_format = | 907 GLenum adjusted_internal_format = |
740 getIntermediateFormat(dest_internal_format); | 908 method == DRAW_AND_READBACK |
909 ? GL_RGBA | |
910 : getIntermediateFormat(dest_internal_format); | |
741 dest_target = GL_TEXTURE_2D; | 911 dest_target = GL_TEXTURE_2D; |
742 glGenTextures(1, &intermediate_texture); | 912 glGenTextures(1, &intermediate_texture); |
743 glBindTexture(dest_target, intermediate_texture); | 913 glBindTexture(dest_target, intermediate_texture); |
744 GLenum format = TextureManager::ExtractFormatFromStorageFormat( | 914 GLenum format = TextureManager::ExtractFormatFromStorageFormat( |
745 adjusted_internal_format); | 915 adjusted_internal_format); |
746 GLenum type = | 916 GLenum type = |
747 TextureManager::ExtractTypeFromStorageFormat(adjusted_internal_format); | 917 TextureManager::ExtractTypeFromStorageFormat(adjusted_internal_format); |
748 | 918 |
749 glTexImage2D(dest_target, 0, adjusted_internal_format, width, height, 0, | 919 glTexImage2D(dest_target, 0, adjusted_internal_format, width, height, 0, |
750 format, type, nullptr); | 920 format, type, nullptr); |
751 dest_texture = intermediate_texture; | 921 dest_texture = intermediate_texture; |
752 dest_level = 0; | 922 dest_level = 0; |
753 dest_internal_format = adjusted_internal_format; | 923 dest_internal_format = adjusted_internal_format; |
754 } | 924 } |
755 // Use kIdentityMatrix if no transform passed in. | 925 // Use kIdentityMatrix if no transform passed in. |
756 DoCopyTextureWithTransform( | 926 DoCopyTextureWithTransform( |
757 decoder, source_target, source_id, source_level, source_internal_format, | 927 decoder, source_target, source_id, source_level, source_internal_format, |
758 dest_target, dest_texture, dest_level, dest_internal_format, width, | 928 dest_target, dest_texture, dest_level, dest_internal_format, width, |
759 height, flip_y, premultiply_alpha, unpremultiply_alpha, kIdentityMatrix); | 929 height, flip_y, premultiply_alpha, unpremultiply_alpha, kIdentityMatrix); |
760 | 930 |
761 if (method == DRAW_AND_COPY) { | 931 if (method == DRAW_AND_COPY || method == DRAW_AND_READBACK) { |
762 source_level = 0; | 932 source_level = 0; |
763 DoCopyTexImage2D(decoder, dest_target, intermediate_texture, source_level, | 933 if (method == DRAW_AND_COPY) { |
764 original_dest_target, dest_id, original_dest_level, | 934 DoCopyTexImage2D(decoder, dest_target, intermediate_texture, source_level, |
765 original_internal_format, width, height, framebuffer_); | 935 original_dest_target, dest_id, original_dest_level, |
936 original_internal_format, width, height, framebuffer_); | |
937 } else if (method == DRAW_AND_READBACK) { | |
938 DoReadbackAndTexImage2D(decoder, dest_target, intermediate_texture, | |
939 source_level, original_dest_target, dest_id, | |
940 original_dest_level, original_internal_format, | |
941 width, height, framebuffer_); | |
942 } | |
766 glDeleteTextures(1, &intermediate_texture); | 943 glDeleteTextures(1, &intermediate_texture); |
767 } | 944 } |
768 } | 945 } |
769 | 946 |
770 void CopyTextureCHROMIUMResourceManager::DoCopySubTexture( | 947 void CopyTextureCHROMIUMResourceManager::DoCopySubTexture( |
771 const gles2::GLES2Decoder* decoder, | 948 const gles2::GLES2Decoder* decoder, |
772 GLenum source_target, | 949 GLenum source_target, |
773 GLuint source_id, | 950 GLuint source_id, |
774 GLint source_level, | 951 GLint source_level, |
775 GLenum source_internal_format, | 952 GLenum source_internal_format, |
(...skipping 22 matching lines...) Expand all Loading... | |
798 return; | 975 return; |
799 } | 976 } |
800 | 977 |
801 // Draw to level 0 of an intermediate GL_TEXTURE_2D texture. | 978 // Draw to level 0 of an intermediate GL_TEXTURE_2D texture. |
802 GLint dest_xoffset = xoffset; | 979 GLint dest_xoffset = xoffset; |
803 GLint dest_yoffset = yoffset; | 980 GLint dest_yoffset = yoffset; |
804 GLuint dest_texture = dest_id; | 981 GLuint dest_texture = dest_id; |
805 GLint original_dest_level = dest_level; | 982 GLint original_dest_level = dest_level; |
806 GLenum original_dest_target = dest_target; | 983 GLenum original_dest_target = dest_target; |
807 GLuint intermediate_texture = 0; | 984 GLuint intermediate_texture = 0; |
808 if (method == DRAW_AND_COPY) { | 985 GLenum original_internal_format = dest_internal_format; |
986 if (method == DRAW_AND_COPY || method == DRAW_AND_READBACK) { | |
809 GLenum adjusted_internal_format = | 987 GLenum adjusted_internal_format = |
810 getIntermediateFormat(dest_internal_format); | 988 method == DRAW_AND_READBACK |
989 ? GL_RGBA | |
990 : getIntermediateFormat(dest_internal_format); | |
811 dest_target = GL_TEXTURE_2D; | 991 dest_target = GL_TEXTURE_2D; |
812 glGenTextures(1, &intermediate_texture); | 992 glGenTextures(1, &intermediate_texture); |
813 glBindTexture(dest_target, intermediate_texture); | 993 glBindTexture(dest_target, intermediate_texture); |
814 GLenum format = TextureManager::ExtractFormatFromStorageFormat( | 994 GLenum format = TextureManager::ExtractFormatFromStorageFormat( |
815 adjusted_internal_format); | 995 adjusted_internal_format); |
816 GLenum type = | 996 GLenum type = |
817 TextureManager::ExtractTypeFromStorageFormat(adjusted_internal_format); | 997 TextureManager::ExtractTypeFromStorageFormat(adjusted_internal_format); |
818 | 998 |
819 glTexImage2D(dest_target, 0, adjusted_internal_format, width, height, 0, | 999 glTexImage2D(dest_target, 0, adjusted_internal_format, width, height, 0, |
820 format, type, nullptr); | 1000 format, type, nullptr); |
821 dest_texture = intermediate_texture; | 1001 dest_texture = intermediate_texture; |
822 dest_level = 0; | 1002 dest_level = 0; |
823 dest_internal_format = adjusted_internal_format; | 1003 dest_internal_format = adjusted_internal_format; |
824 dest_xoffset = 0; | 1004 dest_xoffset = 0; |
825 dest_yoffset = 0; | 1005 dest_yoffset = 0; |
826 dest_width = width; | 1006 dest_width = width; |
827 dest_height = height; | 1007 dest_height = height; |
828 } | 1008 } |
829 | 1009 |
830 DoCopySubTextureWithTransform( | 1010 DoCopySubTextureWithTransform( |
831 decoder, source_target, source_id, source_level, source_internal_format, | 1011 decoder, source_target, source_id, source_level, source_internal_format, |
832 dest_target, dest_texture, dest_level, dest_internal_format, dest_xoffset, | 1012 dest_target, dest_texture, dest_level, dest_internal_format, dest_xoffset, |
833 dest_yoffset, x, y, width, height, dest_width, dest_height, source_width, | 1013 dest_yoffset, x, y, width, height, dest_width, dest_height, source_width, |
834 source_height, flip_y, premultiply_alpha, unpremultiply_alpha, | 1014 source_height, flip_y, premultiply_alpha, unpremultiply_alpha, |
835 kIdentityMatrix); | 1015 kIdentityMatrix); |
836 | 1016 |
837 if (method == DRAW_AND_COPY) { | 1017 if (method == DRAW_AND_COPY || method == DRAW_AND_READBACK) { |
838 source_level = 0; | 1018 source_level = 0; |
839 DoCopyTexSubImage2D(decoder, dest_target, intermediate_texture, | 1019 if (method == DRAW_AND_COPY) { |
840 source_level, original_dest_target, dest_id, | 1020 DoCopyTexSubImage2D(decoder, dest_target, intermediate_texture, |
841 original_dest_level, xoffset, yoffset, 0, 0, width, | 1021 source_level, original_dest_target, dest_id, |
842 height, framebuffer_); | 1022 original_dest_level, xoffset, yoffset, 0, 0, width, |
1023 height, framebuffer_); | |
1024 } else if (method == DRAW_AND_READBACK) { | |
1025 DoReadbackAndTexSubImage2D(decoder, dest_target, intermediate_texture, | |
1026 source_level, original_dest_target, dest_id, | |
1027 original_dest_level, original_internal_format, | |
1028 xoffset, yoffset, width, height, framebuffer_); | |
1029 } | |
843 glDeleteTextures(1, &intermediate_texture); | 1030 glDeleteTextures(1, &intermediate_texture); |
844 } | 1031 } |
845 } | 1032 } |
846 | 1033 |
847 void CopyTextureCHROMIUMResourceManager::DoCopySubTextureWithTransform( | 1034 void CopyTextureCHROMIUMResourceManager::DoCopySubTextureWithTransform( |
848 const gles2::GLES2Decoder* decoder, | 1035 const gles2::GLES2Decoder* decoder, |
849 GLenum source_target, | 1036 GLenum source_target, |
850 GLuint source_id, | 1037 GLuint source_id, |
851 GLint source_level, | 1038 GLint source_level, |
852 GLenum source_internal_format, | 1039 GLenum source_internal_format, |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1133 decoder->RestoreTextureUnitBindings(0); | 1320 decoder->RestoreTextureUnitBindings(0); |
1134 decoder->RestoreActiveTexture(); | 1321 decoder->RestoreActiveTexture(); |
1135 decoder->RestoreProgramBindings(); | 1322 decoder->RestoreProgramBindings(); |
1136 decoder->RestoreBufferBindings(); | 1323 decoder->RestoreBufferBindings(); |
1137 decoder->RestoreFramebufferBindings(); | 1324 decoder->RestoreFramebufferBindings(); |
1138 decoder->RestoreGlobalState(); | 1325 decoder->RestoreGlobalState(); |
1139 } | 1326 } |
1140 | 1327 |
1141 } // namespace gles2 | 1328 } // namespace gles2 |
1142 } // namespace gpu | 1329 } // namespace gpu |
OLD | NEW |