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

Side by Side Diff: gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc

Issue 2760843002: Add readback path for CopyTextureCHROMIUM (Closed)
Patch Set: Created 3 years, 9 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 (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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698