OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrGLGpu.h" | 8 #include "GrGLGpu.h" |
9 #include "GrGLGLSL.h" | 9 #include "GrGLGLSL.h" |
10 #include "GrGLStencilAttachment.h" | 10 #include "GrGLStencilAttachment.h" |
11 #include "GrGLTextureRenderTarget.h" | 11 #include "GrGLTextureRenderTarget.h" |
12 #include "GrGpuResourcePriv.h" | 12 #include "GrGpuResourcePriv.h" |
13 #include "GrPipeline.h" | 13 #include "GrPipeline.h" |
14 #include "GrPLSGeometryProcessor.h" | 14 #include "GrPLSGeometryProcessor.h" |
15 #include "GrRenderTargetPriv.h" | 15 #include "GrRenderTargetPriv.h" |
16 #include "GrSurfacePriv.h" | 16 #include "GrSurfacePriv.h" |
17 #include "GrTexturePriv.h" | 17 #include "GrTexturePriv.h" |
18 #include "GrTypes.h" | 18 #include "GrTypes.h" |
19 #include "GrVertices.h" | 19 #include "GrVertices.h" |
20 #include "builders/GrGLShaderStringBuilder.h" | 20 #include "builders/GrGLShaderStringBuilder.h" |
21 #include "glsl/GrGLSL.h" | 21 #include "glsl/GrGLSL.h" |
22 #include "glsl/GrGLSLCaps.h" | 22 #include "glsl/GrGLSLCaps.h" |
23 #include "glsl/GrGLSLPLSPathRendering.h" | 23 #include "glsl/GrGLSLPLSPathRendering.h" |
24 #include "SkMipMap.h" | |
25 #include "SkPixmap.h" | |
24 #include "SkStrokeRec.h" | 26 #include "SkStrokeRec.h" |
25 #include "SkTemplates.h" | 27 #include "SkTemplates.h" |
28 #include "SkTypes.h" | |
26 | 29 |
27 #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X) | 30 #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X) |
28 #define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->glInterface(), RET, X) | 31 #define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->glInterface(), RET, X) |
29 | 32 |
30 #define SKIP_CACHE_CHECK true | 33 #define SKIP_CACHE_CHECK true |
31 | 34 |
32 #if GR_GL_CHECK_ALLOC_WITH_GET_ERROR | 35 #if GR_GL_CHECK_ALLOC_WITH_GET_ERROR |
33 #define CLEAR_ERROR_BEFORE_ALLOC(iface) GrGLClearErr(iface) | 36 #define CLEAR_ERROR_BEFORE_ALLOC(iface) GrGLClearErr(iface) |
34 #define GL_ALLOC_CALL(iface, call) GR_GL_CALL_NOERRCHECK(iface, call) | 37 #define GL_ALLOC_CALL(iface, call) GR_GL_CALL_NOERRCHECK(iface, call) |
35 #define CHECK_ALLOC_ERROR(iface) GR_GL_GET_ERROR(iface) | 38 #define CHECK_ALLOC_ERROR(iface) GR_GL_GET_ERROR(iface) |
36 #else | 39 #else |
37 #define CLEAR_ERROR_BEFORE_ALLOC(iface) | 40 #define CLEAR_ERROR_BEFORE_ALLOC(iface) |
38 #define GL_ALLOC_CALL(iface, call) GR_GL_CALL(iface, call) | 41 #define GL_ALLOC_CALL(iface, call) GR_GL_CALL(iface, call) |
39 #define CHECK_ALLOC_ERROR(iface) GR_GL_NO_ERROR | 42 #define CHECK_ALLOC_ERROR(iface) GR_GL_NO_ERROR |
40 #endif | 43 #endif |
41 | 44 |
45 #if defined(GOOGLE3) | |
46 // Stack frame size is limited in GOOGLE3. | |
47 typedef SkAutoSMalloc<64 * 128> SkAutoSMallocTexels; | |
48 #else | |
49 typedef SkAutoSMalloc<128 * 128> SkAutoSMallocTexels; | |
50 #endif | |
51 | |
42 /////////////////////////////////////////////////////////////////////////////// | 52 /////////////////////////////////////////////////////////////////////////////// |
43 | 53 |
44 | 54 |
45 static const GrGLenum gXfermodeEquation2Blend[] = { | 55 static const GrGLenum gXfermodeEquation2Blend[] = { |
46 // Basic OpenGL blend equations. | 56 // Basic OpenGL blend equations. |
47 GR_GL_FUNC_ADD, | 57 GR_GL_FUNC_ADD, |
48 GR_GL_FUNC_SUBTRACT, | 58 GR_GL_FUNC_SUBTRACT, |
49 GR_GL_FUNC_REVERSE_SUBTRACT, | 59 GR_GL_FUNC_REVERSE_SUBTRACT, |
50 | 60 |
51 // GL_KHR_blend_equation_advanced. | 61 // GL_KHR_blend_equation_advanced. |
(...skipping 690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
742 // Write or transfer of pixels is not implemented for TEXTURE_EXTERNAL textu res | 752 // Write or transfer of pixels is not implemented for TEXTURE_EXTERNAL textu res |
743 if (GR_GL_TEXTURE_EXTERNAL == glTex->target()) { | 753 if (GR_GL_TEXTURE_EXTERNAL == glTex->target()) { |
744 return false; | 754 return false; |
745 } | 755 } |
746 | 756 |
747 return true; | 757 return true; |
748 } | 758 } |
749 | 759 |
750 bool GrGLGpu::onWritePixels(GrSurface* surface, | 760 bool GrGLGpu::onWritePixels(GrSurface* surface, |
751 int left, int top, int width, int height, | 761 int left, int top, int width, int height, |
752 GrPixelConfig config, const void* buffer, | 762 GrPixelConfig config, |
753 size_t rowBytes) { | 763 const SkTArray<GrMipLevel>& texels) { |
754 GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture()); | 764 GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture()); |
755 | 765 |
756 if (!check_write_and_transfer_input(glTex, surface, config)) { | 766 if (!check_write_and_transfer_input(glTex, surface, config)) { |
757 return false; | 767 return false; |
758 } | 768 } |
759 | 769 |
760 this->setScratchTextureUnit(); | 770 this->setScratchTextureUnit(); |
761 GL_CALL(BindTexture(glTex->target(), glTex->textureID())); | 771 GL_CALL(BindTexture(glTex->target(), glTex->textureID())); |
762 | 772 |
763 bool success = false; | 773 bool success = false; |
764 if (GrPixelConfigIsCompressed(glTex->desc().fConfig)) { | 774 if (GrPixelConfigIsCompressed(glTex->desc().fConfig)) { |
765 // We check that config == desc.fConfig in GrGLGpu::canWriteTexturePixel s() | 775 // We check that config == desc.fConfig in GrGLGpu::canWriteTexturePixel s() |
766 SkASSERT(config == glTex->desc().fConfig); | 776 SkASSERT(config == glTex->desc().fConfig); |
767 success = this->uploadCompressedTexData(glTex->desc(), glTex->target(), buffer, | 777 success = this->uploadCompressedTexData(glTex->desc(), glTex->target(), texels, |
768 kWrite_UploadType, left, top, wi dth, height); | 778 kWrite_UploadType, left, top, wi dth, height); |
769 } else { | 779 } else { |
770 success = this->uploadTexData(glTex->desc(), glTex->target(), kWrite_Upl oadType, | 780 success = this->uploadTexData(glTex->desc(), glTex->target(), kWrite_Upl oadType, |
771 left, top, width, height, config, buffer, rowBytes); | 781 left, top, width, height, config, texels); |
772 } | 782 } |
773 | 783 |
774 if (success) { | 784 return success; |
775 glTex->texturePriv().dirtyMipMaps(true); | |
776 return true; | |
777 } | |
778 | |
779 return false; | |
780 } | 785 } |
781 | 786 |
782 bool GrGLGpu::onTransferPixels(GrSurface* surface, | 787 bool GrGLGpu::onTransferPixels(GrSurface* surface, |
783 int left, int top, int width, int height, | 788 int left, int top, int width, int height, |
784 GrPixelConfig config, GrTransferBuffer* buffer, | 789 GrPixelConfig config, GrTransferBuffer* buffer, |
785 size_t offset, size_t rowBytes) { | 790 size_t offset, size_t rowBytes) { |
786 GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture()); | 791 GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture()); |
787 | 792 |
788 if (!check_write_and_transfer_input(glTex, surface, config)) { | 793 if (!check_write_and_transfer_input(glTex, surface, config)) { |
789 return false; | 794 return false; |
790 } | 795 } |
791 | 796 |
792 // For the moment, can't transfer compressed data | 797 // For the moment, can't transfer compressed data |
793 if (GrPixelConfigIsCompressed(glTex->desc().fConfig)) { | 798 if (GrPixelConfigIsCompressed(glTex->desc().fConfig)) { |
794 return false; | 799 return false; |
795 } | 800 } |
796 | 801 |
797 this->setScratchTextureUnit(); | 802 this->setScratchTextureUnit(); |
798 GL_CALL(BindTexture(glTex->target(), glTex->textureID())); | 803 GL_CALL(BindTexture(glTex->target(), glTex->textureID())); |
799 | 804 |
800 SkASSERT(!buffer->isMapped()); | 805 SkASSERT(!buffer->isMapped()); |
801 GrGLTransferBuffer* glBuffer = reinterpret_cast<GrGLTransferBuffer*>(buffer) ; | 806 GrGLTransferBuffer* glBuffer = reinterpret_cast<GrGLTransferBuffer*>(buffer) ; |
802 // bind the transfer buffer | 807 // bind the transfer buffer |
803 SkASSERT(GR_GL_PIXEL_UNPACK_BUFFER == glBuffer->bufferType() || | 808 SkASSERT(GR_GL_PIXEL_UNPACK_BUFFER == glBuffer->bufferType() || |
804 GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM == glBuffer->bufferType ()); | 809 GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM == glBuffer->bufferType ()); |
805 GL_CALL(BindBuffer(glBuffer->bufferType(), glBuffer->bufferID())); | 810 GL_CALL(BindBuffer(glBuffer->bufferType(), glBuffer->bufferID())); |
806 | 811 |
807 bool success = false; | 812 bool success = false; |
813 GrMipLevel mipLevel; | |
814 mipLevel.fPixels = buffer; | |
815 mipLevel.fRowBytes = rowBytes; | |
816 SkSTArray<1, GrMipLevel> texels; | |
817 texels.push_back(mipLevel); | |
808 success = this->uploadTexData(glTex->desc(), glTex->target(), kTransfer_Uplo adType, | 818 success = this->uploadTexData(glTex->desc(), glTex->target(), kTransfer_Uplo adType, |
809 left, top, width, height, config, buffer, rowB ytes); | 819 left, top, width, height, config, texels); |
810 | |
811 if (success) { | 820 if (success) { |
812 glTex->texturePriv().dirtyMipMaps(true); | 821 glTex->texturePriv().dirtyMipMaps(true); |
813 return true; | 822 return true; |
814 } | 823 } |
815 | 824 |
816 return false; | 825 return false; |
817 } | 826 } |
818 | 827 |
819 // For GL_[UN]PACK_ALIGNMENT. | 828 // For GL_[UN]PACK_ALIGNMENT. |
820 static inline GrGLint config_alignment(GrPixelConfig config) { | 829 static inline GrGLint config_alignment(GrPixelConfig config) { |
(...skipping 18 matching lines...) Expand all Loading... | |
839 | 848 |
840 static inline GrGLenum check_alloc_error(const GrSurfaceDesc& desc, | 849 static inline GrGLenum check_alloc_error(const GrSurfaceDesc& desc, |
841 const GrGLInterface* interface) { | 850 const GrGLInterface* interface) { |
842 if (SkToBool(desc.fFlags & kCheckAllocation_GrSurfaceFlag)) { | 851 if (SkToBool(desc.fFlags & kCheckAllocation_GrSurfaceFlag)) { |
843 return GR_GL_GET_ERROR(interface); | 852 return GR_GL_GET_ERROR(interface); |
844 } else { | 853 } else { |
845 return CHECK_ALLOC_ERROR(interface); | 854 return CHECK_ALLOC_ERROR(interface); |
846 } | 855 } |
847 } | 856 } |
848 | 857 |
858 /** | |
859 * Creates storage space for the texture and fills it with texels. | |
860 * | |
861 * @param desc The surface descriptor for the texture being created. | |
862 * @param interface The GL interface in use. | |
863 * @param useTexStorage The result of a call to can_use_tex_storage(). | |
864 * @param internalFormat The data format used for the internal storage of the te xture. | |
865 * @param externalFormat The data format used for the external storage of the te xture. | |
866 * @param externalType The type of the data used for the external storage of t he texture. | |
867 * @param texels The texel data of the texture being created. | |
868 * @param baseWidth The width of the texture's base mipmap level | |
869 * @param baseHeight The height of the texture's base mipmap level | |
870 * @param succeeded Set to true if allocating and populating the texture co mpleted | |
871 * without error. | |
872 */ | |
873 static void allocate_and_populate_uncompressed_texture(const GrSurfaceDesc& desc , | |
874 const GrGLInterface& inte rface, | |
875 GrGLenum target, | |
876 GrGLenum internalFormat, | |
877 GrGLenum externalFormat, | |
878 GrGLenum externalType, | |
879 const SkTArray<GrMipLevel >& texels, | |
880 int baseWidth, int baseHe ight, | |
881 bool* succeeded) { | |
882 CLEAR_ERROR_BEFORE_ALLOC(&interface); | |
883 *succeeded = true; | |
884 for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLe vel++) { | |
885 int twoToTheMipLevel = 1 << currentMipLevel; | |
886 int currentWidth = SkTMax(1, baseWidth / twoToTheMipLevel); | |
887 int currentHeight = SkTMax(1, baseHeight / twoToTheMipLevel); | |
888 const void* currentMipData = texels[currentMipLevel].fPixels; | |
889 // Even if curremtMipData is nullptr, continue to call TexImage2D. | |
890 // This will allocate texture memory which we can later populate. | |
891 GL_ALLOC_CALL(&interface, | |
892 TexImage2D(target, | |
893 currentMipLevel, | |
894 internalFormat, | |
895 currentWidth, | |
896 currentHeight, | |
897 0, // border | |
898 externalFormat, externalType, | |
899 currentMipData)); | |
900 GrGLenum error = check_alloc_error(desc, &interface); | |
901 if (error != GR_GL_NO_ERROR) { | |
902 *succeeded = false; | |
903 break; | |
904 } | |
905 } | |
906 } | |
907 | |
908 /** | |
909 * Creates storage space for the texture and fills it with texels. | |
910 * | |
911 * @param desc The surface descriptor for the texture being created. | |
912 * @param interface The GL interface in use. | |
913 * @param useTexStorage The result of a call to can_use_tex_storage(). | |
914 * @param internalFormat The data format used for the internal storage of the te xture. | |
915 * @param texels The texel data of the texture being created. | |
916 */ | |
917 static bool allocate_and_populate_compressed_texture(const GrSurfaceDesc& desc, | |
918 const GrGLInterface& interf ace, | |
919 GrGLenum target, GrGLenum i nternalFormat, | |
920 const SkTArray<GrMipLevel>& texels, | |
921 int baseWidth, int baseHeig ht) { | |
922 CLEAR_ERROR_BEFORE_ALLOC(&interface); | |
923 for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLe vel++) { | |
924 int twoToTheMipLevel = 1 << currentMipLevel; | |
925 int currentWidth = SkTMax(1, baseWidth / twoToTheMipLevel); | |
926 int currentHeight = SkTMax(1, baseHeight / twoToTheMipLevel); | |
927 | |
928 // Make sure that the width and height that we pass to OpenGL | |
929 // is a multiple of the block size. | |
930 size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, baseWidth, ba seHeight); | |
931 | |
932 GL_ALLOC_CALL(&interface, | |
933 CompressedTexImage2D(target, | |
934 currentMipLevel, | |
935 internalFormat, | |
936 currentWidth, | |
937 currentHeight, | |
938 0, // border | |
939 SkToInt(dataSize), | |
940 texels[currentMipLevel].fPixels)); | |
941 | |
942 GrGLenum error = check_alloc_error(desc, &interface); | |
943 if (error != GR_GL_NO_ERROR) { | |
944 return false; | |
945 } | |
946 } | |
947 | |
948 return true; | |
949 } | |
950 | |
951 /** | |
952 * After a texture is created, any state which was altered during its creation | |
953 * needs to be restored. | |
954 * | |
955 * @param interface The GL interface to use. | |
956 * @param caps The capabilities of the GL device. | |
957 * @param restoreGLRowLength Should the row length unpacking be restored? | |
958 * @param glFlipY Did GL flip the texture vertically? | |
959 */ | |
960 static void restore_pixelstore_state(const GrGLInterface& interface, const GrGLC aps& caps, | |
961 bool restoreGLRowLength, bool glFlipY) { | |
962 if (restoreGLRowLength) { | |
963 SkASSERT(caps.unpackRowLengthSupport()); | |
964 GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0)); | |
965 } | |
966 if (glFlipY) { | |
967 GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE)); | |
968 } | |
969 } | |
970 | |
849 bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc, | 971 bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc, |
850 GrGLenum target, | 972 GrGLenum target, |
851 UploadType uploadType, | 973 UploadType uploadType, |
852 int left, int top, int width, int height, | 974 int left, int top, int width, int height, |
853 GrPixelConfig dataConfig, | 975 GrPixelConfig dataConfig, |
854 const void* dataOrOffset, | 976 const SkTArray<GrMipLevel>& texels) { |
855 size_t rowBytes) { | |
856 SkASSERT(dataOrOffset || kNewTexture_UploadType == uploadType || | |
857 kTransfer_UploadType == uploadType); | |
858 | |
859 // If we're uploading compressed data then we should be using uploadCompress edTexData | 977 // If we're uploading compressed data then we should be using uploadCompress edTexData |
860 SkASSERT(!GrPixelConfigIsCompressed(dataConfig)); | 978 SkASSERT(!GrPixelConfigIsCompressed(dataConfig)); |
861 | 979 |
862 SkASSERT(this->caps()->isConfigTexturable(desc.fConfig)); | 980 SkASSERT(this->caps()->isConfigTexturable(desc.fConfig)); |
863 | 981 |
982 // texels is const. | |
983 // But we may need to flip the texture vertically to prepare it. | |
984 // Rather than flip in place and alter the incoming data, | |
985 // we allocate a new buffer to flip into. | |
986 // This means we need to make a non-const shallow copy of texels. | |
987 SkTArray<GrMipLevel> texelsShallowCopy(texels); | |
988 | |
989 for (int currentMipLevel = texelsShallowCopy.count() - 1; currentMipLevel >= 0; | |
990 currentMipLevel--) { | |
991 SkASSERT(texelsShallowCopy[currentMipLevel].fPixels || | |
992 kNewTexture_UploadType == uploadType || kTransfer_UploadType == uploadType); | |
993 } | |
994 | |
995 const GrGLInterface* interface = this->glInterface(); | |
996 const GrGLCaps& caps = this->glCaps(); | |
997 | |
864 size_t bpp = GrBytesPerPixel(dataConfig); | 998 size_t bpp = GrBytesPerPixel(dataConfig); |
865 if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, & left, &top, | 999 |
866 &width, &height, &dataOrOffset, & rowBytes)) { | 1000 if (width == 0 || height == 0) { |
867 return false; | 1001 return false; |
868 } | 1002 } |
869 size_t trimRowBytes = width * bpp; | |
870 | 1003 |
871 // in case we need a temporary, trimmed copy of the src pixels | 1004 for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); c urrentMipLevel++) { |
872 SkAutoSMalloc<128 * 128> tempStorage; | 1005 int twoToTheMipLevel = 1 << currentMipLevel; |
1006 int currentWidth = SkTMax(1, width / twoToTheMipLevel); | |
1007 int currentHeight = SkTMax(1, height / twoToTheMipLevel); | |
1008 | |
1009 if (texelsShallowCopy[currentMipLevel].fPixels == nullptr) { | |
1010 continue; | |
1011 } | |
1012 | |
1013 if (currentHeight > SK_MaxS32 || | |
1014 currentWidth > SK_MaxS32) { | |
1015 return false; | |
1016 } | |
1017 if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bp p, &left, &top, | |
1018 ¤tWidth, | |
1019 ¤tHeight, | |
1020 &texelsShallowCopy[currentMipLeve l].fPixels, | |
1021 &texelsShallowCopy[currentMipLeve l].fRowBytes)) { | |
1022 return false; | |
1023 } | |
1024 if (currentWidth < 0 || currentHeight < 0) { | |
1025 return false; | |
1026 } | |
1027 } | |
873 | 1028 |
874 // Internal format comes from the texture desc. | 1029 // Internal format comes from the texture desc. |
875 GrGLenum internalFormat; | 1030 GrGLenum internalFormat; |
876 // External format and type come from the upload data. | 1031 // External format and type come from the upload data. |
877 GrGLenum externalFormat; | 1032 GrGLenum externalFormat; |
878 GrGLenum externalType; | 1033 GrGLenum externalType; |
879 if (!this->glCaps().getTexImageFormats(desc.fConfig, dataConfig, &internalFo rmat, | 1034 if (!this->glCaps().getTexImageFormats(desc.fConfig, dataConfig, &internalFo rmat, |
880 &externalFormat, &externalType)) { | 1035 &externalFormat, &externalType)) { |
881 return false; | 1036 return false; |
882 } | 1037 } |
883 /* | 1038 /* |
884 * Check whether to allocate a temporary buffer for flipping y or | 1039 * Check whether to allocate a temporary buffer for flipping y or |
885 * because our srcData has extra bytes past each row. If so, we need | 1040 * because our srcData has extra bytes past each row. If so, we need |
886 * to trim those off here, since GL ES may not let us specify | 1041 * to trim those off here, since GL ES may not let us specify |
887 * GL_UNPACK_ROW_LENGTH. | 1042 * GL_UNPACK_ROW_LENGTH. |
888 */ | 1043 */ |
889 bool restoreGLRowLength = false; | 1044 bool restoreGLRowLength = false; |
890 bool swFlipY = false; | 1045 bool swFlipY = false; |
891 bool glFlipY = false; | 1046 bool glFlipY = false; |
892 if (dataOrOffset) { | 1047 |
893 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { | 1048 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { |
894 if (this->glCaps().unpackFlipYSupport()) { | 1049 if (caps.unpackFlipYSupport()) { |
895 glFlipY = true; | 1050 glFlipY = true; |
896 } else { | 1051 } else { |
897 swFlipY = true; | 1052 swFlipY = true; |
898 } | |
899 } | 1053 } |
900 if (this->glCaps().unpackRowLengthSupport() && !swFlipY) { | 1054 } |
1055 | |
1056 // in case we need a temporary, trimmed copy of the src pixels | |
1057 SkAutoSMallocTexels tempStorage; | |
1058 | |
1059 // find the combined size of all the mip levels and the relative offset of | |
1060 // each into the collective buffer | |
1061 size_t combined_buffer_size = 0; | |
1062 SkTArray<size_t> individual_mip_offsets(texelsShallowCopy.count()); | |
1063 for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); c urrentMipLevel++) { | |
1064 int twoToTheMipLevel = 1 << currentMipLevel; | |
1065 int currentWidth = SkTMax(1, width / twoToTheMipLevel); | |
1066 int currentHeight = SkTMax(1, height / twoToTheMipLevel); | |
1067 const size_t trimmedSize = currentWidth * bpp * currentHeight; | |
1068 individual_mip_offsets.push_back(combined_buffer_size); | |
1069 combined_buffer_size += trimmedSize; | |
1070 } | |
1071 char* buffer = (char*)tempStorage.reset(combined_buffer_size); | |
1072 | |
1073 for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); c urrentMipLevel++) { | |
1074 if (texelsShallowCopy[currentMipLevel].fPixels == nullptr) { | |
1075 continue; | |
1076 } | |
1077 | |
1078 int twoToTheMipLevel = 1 << currentMipLevel; | |
1079 int currentWidth = SkTMax(1, width / twoToTheMipLevel); | |
1080 int currentHeight = SkTMax(1, height / twoToTheMipLevel); | |
1081 const size_t trimRowBytes = currentWidth * bpp; | |
1082 | |
1083 /* | |
1084 * check whether to allocate a temporary buffer for flipping y or | |
1085 * because our srcData has extra bytes past each row. If so, we need | |
1086 * to trim those off here, since GL ES may not let us specify | |
1087 * GL_UNPACK_ROW_LENGTH. | |
1088 */ | |
1089 restoreGLRowLength = false; | |
1090 | |
1091 const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes; | |
1092 if (caps.unpackRowLengthSupport() && !swFlipY) { | |
901 // can't use this for flipping, only non-neg values allowed. :( | 1093 // can't use this for flipping, only non-neg values allowed. :( |
902 if (rowBytes != trimRowBytes) { | 1094 if (rowBytes != trimRowBytes) { |
903 GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp); | 1095 GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp); |
904 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength)); | 1096 GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLe ngth)); |
905 restoreGLRowLength = true; | 1097 restoreGLRowLength = true; |
906 } | 1098 } |
907 } else if (kTransfer_UploadType != uploadType) { | 1099 } else if (kTransfer_UploadType != uploadType) { |
908 if (trimRowBytes != rowBytes || swFlipY) { | 1100 if (trimRowBytes != rowBytes || swFlipY) { |
909 // copy data into our new storage, skipping the trailing bytes | 1101 // copy data into our new storage, skipping the trailing bytes |
910 size_t trimSize = height * trimRowBytes; | 1102 const char* src = (const char*)texelsShallowCopy[currentMipLevel ].fPixels; |
911 const char* src = (const char*)dataOrOffset; | 1103 if (swFlipY && currentHeight >= 1) { |
912 if (swFlipY) { | 1104 src += (currentHeight - 1) * rowBytes; |
913 src += (height - 1) * rowBytes; | |
914 } | 1105 } |
915 char* dst = (char*)tempStorage.reset(trimSize); | 1106 char* dst = buffer + individual_mip_offsets[currentMipLevel]; |
916 for (int y = 0; y < height; y++) { | 1107 for (int y = 0; y < currentHeight; y++) { |
917 memcpy(dst, src, trimRowBytes); | 1108 memcpy(dst, src, trimRowBytes); |
918 if (swFlipY) { | 1109 if (swFlipY) { |
919 src -= rowBytes; | 1110 src -= rowBytes; |
920 } else { | 1111 } else { |
921 src += rowBytes; | 1112 src += rowBytes; |
922 } | 1113 } |
923 dst += trimRowBytes; | 1114 dst += trimRowBytes; |
924 } | 1115 } |
925 // now point data to our copied version | 1116 // now point data to our copied version |
926 dataOrOffset = tempStorage.get(); | 1117 texelsShallowCopy[currentMipLevel].fPixels = buffer + |
1118 individual_mip_offsets[currentMipLevel]; | |
1119 texelsShallowCopy[currentMipLevel].fRowBytes = trimRowBytes; | |
927 } | 1120 } |
928 } else { | 1121 } else { |
929 return false; | 1122 return false; |
930 } | 1123 } |
931 if (glFlipY) { | 1124 if (glFlipY) { |
932 GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE)); | 1125 GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE)); |
933 } | 1126 } |
934 GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, config_alignment(dataConfig) )); | 1127 GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ALIGNMENT, |
1128 config_alignment(desc.fConfig))); | |
935 } | 1129 } |
1130 | |
936 bool succeeded = true; | 1131 bool succeeded = true; |
937 if (kNewTexture_UploadType == uploadType) { | 1132 if (kNewTexture_UploadType == uploadType && |
938 if (dataOrOffset && | 1133 0 == left && 0 == top && |
939 !(0 == left && 0 == top && desc.fWidth == width && desc.fHeight == h eight)) { | 1134 desc.fWidth == width && desc.fHeight == height && |
940 succeeded = false; | 1135 !desc.fTextureStorageAllocator.fAllocateTextureStorage) { |
941 } else { | 1136 allocate_and_populate_uncompressed_texture(desc, *interface, target, |
942 if (desc.fTextureStorageAllocator.fAllocateTextureStorage) { | 1137 internalFormat, externalForma t, |
943 if (dataOrOffset) { | 1138 externalType, texelsShallowCo py, |
944 GL_CALL(TexSubImage2D(target, | 1139 width, height, &succeeded); |
945 0, // level | |
946 left, top, | |
947 width, height, | |
948 externalFormat, externalType, dataOrOf fset)); | |
949 } | |
950 } else { | |
951 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); | |
952 GL_ALLOC_CALL(this->glInterface(), TexImage2D( | |
953 target, 0, internalFormat, desc.fWidth, desc.fHeight, 0, ext ernalFormat, | |
954 externalType, dataOrOffset)); | |
955 GrGLenum error = check_alloc_error(desc, this->glInterface()); | |
956 if (error != GR_GL_NO_ERROR) { | |
957 succeeded = false; | |
958 } | |
959 } | |
960 } | |
961 } else { | 1140 } else { |
962 if (swFlipY || glFlipY) { | 1141 if (swFlipY || glFlipY) { |
963 top = desc.fHeight - (top + height); | 1142 top = desc.fHeight - (top + height); |
964 } | 1143 } |
965 GL_CALL(TexSubImage2D(target, | 1144 for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count( ); |
966 0, // level | 1145 currentMipLevel++) { |
967 left, top, | 1146 int twoToTheMipLevel = 1 << currentMipLevel; |
968 width, height, | 1147 int currentWidth = SkTMax(1, width / twoToTheMipLevel); |
969 externalFormat, externalType, dataOrOffset)); | 1148 int currentHeight = SkTMax(1, height / twoToTheMipLevel); |
1149 if (texelsShallowCopy[currentMipLevel].fPixels == nullptr) { | |
1150 continue; | |
1151 } | |
1152 | |
1153 GL_CALL(TexSubImage2D(target, | |
1154 currentMipLevel, | |
1155 left, top, | |
1156 currentWidth, | |
1157 currentHeight, | |
1158 externalFormat, externalType, | |
1159 texelsShallowCopy[currentMipLevel].fPixels)); | |
1160 } | |
970 } | 1161 } |
971 | 1162 |
972 if (restoreGLRowLength) { | 1163 restore_pixelstore_state(*interface, caps, restoreGLRowLength, glFlipY); |
973 SkASSERT(this->glCaps().unpackRowLengthSupport()); | 1164 |
974 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0)); | |
975 } | |
976 if (glFlipY) { | |
977 GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE)); | |
978 } | |
979 return succeeded; | 1165 return succeeded; |
980 } | 1166 } |
981 | 1167 |
982 // TODO: This function is using a lot of wonky semantics like, if width == -1 | 1168 // TODO: This function is using a lot of wonky semantics like, if width == -1 |
983 // then set width = desc.fWdith ... blah. A better way to do it might be to | 1169 // then set width = desc.fWdith ... blah. A better way to do it might be to |
984 // create a CompressedTexData struct that takes a desc/ptr and figures out | 1170 // create a CompressedTexData struct that takes a desc/ptr and figures out |
985 // the proper upload semantics. Then users can construct this function how they | 1171 // the proper upload semantics. Then users can construct this function how they |
986 // see fit if they want to go against the "standard" way to do it. | 1172 // see fit if they want to go against the "standard" way to do it. |
987 bool GrGLGpu::uploadCompressedTexData(const GrSurfaceDesc& desc, | 1173 bool GrGLGpu::uploadCompressedTexData(const GrSurfaceDesc& desc, |
988 GrGLenum target, | 1174 GrGLenum target, |
989 const void* data, | 1175 const SkTArray<GrMipLevel>& texels, |
990 UploadType uploadType, | 1176 UploadType uploadType, |
991 int left, int top, int width, int height) { | 1177 int left, int top, int width, int height) { |
992 SkASSERT(this->caps()->isConfigTexturable(desc.fConfig)); | 1178 SkASSERT(this->caps()->isConfigTexturable(desc.fConfig)); |
993 SkASSERT(kTransfer_UploadType != uploadType && | 1179 SkASSERT(kTransfer_UploadType != uploadType && |
994 (data || kNewTexture_UploadType != uploadType)); | 1180 (texels[0].fPixels || kNewTexture_UploadType != uploadType)); |
995 | 1181 |
996 // No support for software flip y, yet... | 1182 // No support for software flip y, yet... |
997 SkASSERT(kBottomLeft_GrSurfaceOrigin != desc.fOrigin); | 1183 SkASSERT(kBottomLeft_GrSurfaceOrigin != desc.fOrigin); |
998 | 1184 |
1185 const GrGLInterface* interface = this->glInterface(); | |
1186 const GrGLCaps& caps = this->glCaps(); | |
1187 | |
999 if (-1 == width) { | 1188 if (-1 == width) { |
1000 width = desc.fWidth; | 1189 width = desc.fWidth; |
1001 } | 1190 } |
1002 #ifdef SK_DEBUG | 1191 #ifdef SK_DEBUG |
1003 else { | 1192 else { |
1004 SkASSERT(width <= desc.fWidth); | 1193 SkASSERT(width <= desc.fWidth); |
1005 } | 1194 } |
1006 #endif | 1195 #endif |
1007 | 1196 |
1008 if (-1 == height) { | 1197 if (-1 == height) { |
1009 height = desc.fHeight; | 1198 height = desc.fHeight; |
1010 } | 1199 } |
1011 #ifdef SK_DEBUG | 1200 #ifdef SK_DEBUG |
1012 else { | 1201 else { |
1013 SkASSERT(height <= desc.fHeight); | 1202 SkASSERT(height <= desc.fHeight); |
1014 } | 1203 } |
1015 #endif | 1204 #endif |
1016 | 1205 |
1017 // Make sure that the width and height that we pass to OpenGL | |
1018 // is a multiple of the block size. | |
1019 size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, width, height); | |
1020 | |
1021 // We only need the internal format for compressed 2D textures. | 1206 // We only need the internal format for compressed 2D textures. |
1022 GrGLenum internalFormat; | 1207 GrGLenum internalFormat; |
1023 if (!this->glCaps().getCompressedTexImageFormats(desc.fConfig, &internalForm at)) { | 1208 if (!caps.getCompressedTexImageFormats(desc.fConfig, &internalFormat)) { |
1024 return false; | 1209 return false; |
1025 } | 1210 } |
1026 | 1211 |
1027 if (kNewTexture_UploadType == uploadType) { | 1212 if (kNewTexture_UploadType == uploadType) { |
1028 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); | 1213 return allocate_and_populate_compressed_texture(desc, *interface, target , internalFormat, |
1029 GL_ALLOC_CALL(this->glInterface(), | 1214 texels, width, height); |
1030 CompressedTexImage2D(target, | |
1031 0, // level | |
1032 internalFormat, | |
1033 width, height, | |
1034 0, // border | |
1035 SkToInt(dataSize), | |
1036 data)); | |
1037 GrGLenum error = check_alloc_error(desc, this->glInterface()); | |
1038 if (error != GR_GL_NO_ERROR) { | |
1039 return false; | |
1040 } | |
1041 } else { | 1215 } else { |
1042 // Paletted textures can't be updated. | 1216 // Paletted textures can't be updated. |
1043 if (GR_GL_PALETTE8_RGBA8 == internalFormat) { | 1217 if (GR_GL_PALETTE8_RGBA8 == internalFormat) { |
1044 return false; | 1218 return false; |
1045 } | 1219 } |
1046 GL_CALL(CompressedTexSubImage2D(target, | 1220 for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentM ipLevel++) { |
1047 0, // level | 1221 if (texels[currentMipLevel].fPixels == nullptr) { |
1048 left, top, | 1222 continue; |
1049 width, height, | 1223 } |
1050 internalFormat, | 1224 |
1051 SkToInt(dataSize), | 1225 int twoToTheMipLevel = 1 << currentMipLevel; |
1052 data)); | 1226 int currentWidth = SkTMax(1, width / twoToTheMipLevel); |
1227 int currentHeight = SkTMax(1, height / twoToTheMipLevel); | |
1228 | |
1229 // Make sure that the width and height that we pass to OpenGL | |
1230 // is a multiple of the block size. | |
1231 size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, currentWi dth, | |
1232 currentHeight); | |
1233 GL_CALL(CompressedTexSubImage2D(target, | |
1234 currentMipLevel, | |
1235 left, top, | |
1236 currentWidth, | |
1237 currentHeight, | |
1238 internalFormat, | |
1239 SkToInt(dataSize), | |
1240 texels[currentMipLevel].fPixels)); | |
1241 } | |
1053 } | 1242 } |
1054 | 1243 |
1055 return true; | 1244 return true; |
1056 } | 1245 } |
1057 | 1246 |
1058 static bool renderbuffer_storage_msaa(const GrGLContext& ctx, | 1247 static bool renderbuffer_storage_msaa(const GrGLContext& ctx, |
1059 int sampleCount, | 1248 int sampleCount, |
1060 GrGLenum format, | 1249 GrGLenum format, |
1061 int width, int height) { | 1250 int width, int height) { |
1062 CLEAR_ERROR_BEFORE_ALLOC(ctx.interface()); | 1251 CLEAR_ERROR_BEFORE_ALLOC(ctx.interface()); |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1206 // SkDEBUGFAIL("null texture"); | 1395 // SkDEBUGFAIL("null texture"); |
1207 return nullptr; | 1396 return nullptr; |
1208 } | 1397 } |
1209 | 1398 |
1210 #if 0 && defined(SK_DEBUG) | 1399 #if 0 && defined(SK_DEBUG) |
1211 static size_t as_size_t(int x) { | 1400 static size_t as_size_t(int x) { |
1212 return x; | 1401 return x; |
1213 } | 1402 } |
1214 #endif | 1403 #endif |
1215 | 1404 |
1405 static GrGLTexture::IDDesc generate_gl_texture(const GrGLInterface* interface, | |
1406 GrGpuResource::LifeCycle lifeCycl e) { | |
1407 GrGLTexture::IDDesc idDesc; | |
1408 idDesc.fInfo.fID = 0; | |
1409 GR_GL_CALL(interface, GenTextures(1, &idDesc.fInfo.fID)); | |
1410 idDesc.fLifeCycle = lifeCycle; | |
1411 // We only support GL_TEXTURE_2D at the moment. | |
bsalomon
2016/02/24 14:43:15
Can we change this to say we only *create* GL_TEXT
cblume
2016/02/24 18:19:19
Done.
| |
1412 idDesc.fInfo.fTarget = GR_GL_TEXTURE_2D; | |
1413 return idDesc; | |
1414 } | |
1415 | |
1416 static void set_initial_texture_params(const GrGLInterface* interface, | |
1417 const GrGLTextureInfo& info, | |
1418 GrGLTexture::TexParams* initialTexParams) { | |
1419 // Some drivers like to know filter/wrap before seeing glTexImage2D. Some | |
1420 // drivers have a bug where an FBO won't be complete if it includes a | |
1421 // texture that is not mipmap complete (considering the filter in use). | |
1422 // we only set a subset here so invalidate first | |
1423 initialTexParams->invalidate(); | |
1424 initialTexParams->fMinFilter = GR_GL_NEAREST; | |
1425 initialTexParams->fMagFilter = GR_GL_NEAREST; | |
1426 initialTexParams->fWrapS = GR_GL_CLAMP_TO_EDGE; | |
1427 initialTexParams->fWrapT = GR_GL_CLAMP_TO_EDGE; | |
1428 GR_GL_CALL(interface, TexParameteri(info.fTarget, | |
1429 GR_GL_TEXTURE_MAG_FILTER, | |
1430 initialTexParams->fMagFilter)); | |
1431 GR_GL_CALL(interface, TexParameteri(info.fTarget, | |
1432 GR_GL_TEXTURE_MIN_FILTER, | |
1433 initialTexParams->fMinFilter)); | |
1434 GR_GL_CALL(interface, TexParameteri(info.fTarget, | |
1435 GR_GL_TEXTURE_WRAP_S, | |
1436 initialTexParams->fWrapS)); | |
1437 GR_GL_CALL(interface, TexParameteri(info.fTarget, | |
1438 GR_GL_TEXTURE_WRAP_T, | |
1439 initialTexParams->fWrapT)); | |
1440 } | |
1441 | |
1216 GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc, | 1442 GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc, |
1217 GrGpuResource::LifeCycle lifeCycle, | 1443 GrGpuResource::LifeCycle lifeCycle, |
1218 const void* srcData, size_t rowBytes) { | 1444 const SkTArray<GrMipLevel>& texels) { |
1219 // We fail if the MSAA was requested and is not available. | 1445 // We fail if the MSAA was requested and is not available. |
1220 if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleC nt) { | 1446 if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleC nt) { |
1221 //SkDebugf("MSAA RT requested but not supported on this platform."); | 1447 //SkDebugf("MSAA RT requested but not supported on this platform."); |
1222 return return_null_texture(); | 1448 return return_null_texture(); |
1223 } | 1449 } |
1224 | 1450 |
1225 bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag); | 1451 bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag); |
1226 | 1452 |
1227 GrGLTexture::IDDesc idDesc; | 1453 GrGLTexture::IDDesc idDesc; |
1228 idDesc.fLifeCycle = lifeCycle; | 1454 idDesc.fLifeCycle = lifeCycle; |
1229 GrGLTexture::TexParams initialTexParams; | 1455 GrGLTexture::TexParams initialTexParams; |
1230 if (!this->createTextureImpl(desc, &idDesc.fInfo, renderTarget, srcData, | 1456 if (!this->createTextureImpl(desc, &idDesc.fInfo, renderTarget, &initialTexP arams, texels)) { |
1231 &initialTexParams, rowBytes)) { | |
1232 return return_null_texture(); | 1457 return return_null_texture(); |
1233 } | 1458 } |
1234 | 1459 |
1235 GrGLTexture* tex; | 1460 GrGLTexture* tex; |
1236 if (renderTarget) { | 1461 if (renderTarget) { |
1237 // unbind the texture from the texture unit before binding it to the fra me buffer | 1462 // unbind the texture from the texture unit before binding it to the fra me buffer |
1238 GL_CALL(BindTexture(idDesc.fInfo.fTarget, 0)); | 1463 GL_CALL(BindTexture(idDesc.fInfo.fTarget, 0)); |
1239 GrGLRenderTarget::IDDesc rtIDDesc; | 1464 GrGLRenderTarget::IDDesc rtIDDesc; |
1240 | 1465 |
1241 if (!this->createRenderTargetObjects(desc, lifeCycle, idDesc.fInfo, &rtI DDesc)) { | 1466 if (!this->createRenderTargetObjects(desc, lifeCycle, idDesc.fInfo, &rtI DDesc)) { |
1242 GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID)); | 1467 GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID)); |
1243 return return_null_texture(); | 1468 return return_null_texture(); |
1244 } | 1469 } |
1245 tex = new GrGLTextureRenderTarget(this, desc, idDesc, rtIDDesc); | 1470 tex = new GrGLTextureRenderTarget(this, desc, idDesc, rtIDDesc); |
1246 } else { | 1471 } else { |
1247 tex = new GrGLTexture(this, desc, idDesc); | 1472 bool wasMipMapDataProvided = false; |
1473 if (texels.count() > 1) { | |
1474 wasMipMapDataProvided = true; | |
1475 } | |
1476 tex = new GrGLTexture(this, desc, idDesc, wasMipMapDataProvided); | |
1248 } | 1477 } |
1249 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); | 1478 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); |
1250 #ifdef TRACE_TEXTURE_CREATION | 1479 #ifdef TRACE_TEXTURE_CREATION |
1251 SkDebugf("--- new texture [%d] size=(%d %d) config=%d\n", | 1480 SkDebugf("--- new texture [%d] size=(%d %d) config=%d\n", |
1252 glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig); | 1481 glTexDesc.fInfo.fID, desc.fWidth, desc.fHeight, desc.fConfig); |
1253 #endif | 1482 #endif |
1254 return tex; | 1483 return tex; |
1255 } | 1484 } |
1256 | 1485 |
1257 GrTexture* GrGLGpu::onCreateCompressedTexture(const GrSurfaceDesc& desc, | 1486 GrTexture* GrGLGpu::onCreateCompressedTexture(const GrSurfaceDesc& desc, |
1258 GrGpuResource::LifeCycle lifeCycle , | 1487 GrGpuResource::LifeCycle lifeCycle , |
1259 const void* srcData) { | 1488 const SkTArray<GrMipLevel>& texels ) { |
1260 // Make sure that we're not flipping Y. | 1489 // Make sure that we're not flipping Y. |
1261 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { | 1490 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { |
1262 return return_null_texture(); | 1491 return return_null_texture(); |
1263 } | 1492 } |
1264 | 1493 |
1265 GrGLTexture::IDDesc idDesc; | 1494 GrGLTexture::IDDesc idDesc = generate_gl_texture(this->glInterface(), lifeCy cle); |
1266 idDesc.fInfo.fID = 0; | |
1267 GL_CALL(GenTextures(1, &idDesc.fInfo.fID)); | |
1268 idDesc.fLifeCycle = lifeCycle; | |
1269 // We only support GL_TEXTURE_2D at the moment. | |
1270 idDesc.fInfo.fTarget = GR_GL_TEXTURE_2D; | |
1271 | |
1272 if (!idDesc.fInfo.fID) { | 1495 if (!idDesc.fInfo.fID) { |
1273 return return_null_texture(); | 1496 return return_null_texture(); |
1274 } | 1497 } |
1275 | 1498 |
1276 this->setScratchTextureUnit(); | 1499 this->setScratchTextureUnit(); |
1277 GL_CALL(BindTexture(idDesc.fInfo.fTarget, idDesc.fInfo.fID)); | 1500 GL_CALL(BindTexture(idDesc.fInfo.fTarget, idDesc.fInfo.fID)); |
1278 | 1501 |
1279 // Some drivers like to know filter/wrap before seeing glTexImage2D. Some | |
1280 // drivers have a bug where an FBO won't be complete if it includes a | |
1281 // texture that is not mipmap complete (considering the filter in use). | |
1282 GrGLTexture::TexParams initialTexParams; | 1502 GrGLTexture::TexParams initialTexParams; |
1283 // we only set a subset here so invalidate first | 1503 set_initial_texture_params(this->glInterface(), idDesc.fInfo, &initialTexPar ams); |
1284 initialTexParams.invalidate(); | |
1285 initialTexParams.fMinFilter = GR_GL_NEAREST; | |
1286 initialTexParams.fMagFilter = GR_GL_NEAREST; | |
1287 initialTexParams.fWrapS = GR_GL_CLAMP_TO_EDGE; | |
1288 initialTexParams.fWrapT = GR_GL_CLAMP_TO_EDGE; | |
1289 GL_CALL(TexParameteri(idDesc.fInfo.fTarget, | |
1290 GR_GL_TEXTURE_MAG_FILTER, | |
1291 initialTexParams.fMagFilter)); | |
1292 GL_CALL(TexParameteri(idDesc.fInfo.fTarget, | |
1293 GR_GL_TEXTURE_MIN_FILTER, | |
1294 initialTexParams.fMinFilter)); | |
1295 GL_CALL(TexParameteri(idDesc.fInfo.fTarget, | |
1296 GR_GL_TEXTURE_WRAP_S, | |
1297 initialTexParams.fWrapS)); | |
1298 GL_CALL(TexParameteri(idDesc.fInfo.fTarget, | |
1299 GR_GL_TEXTURE_WRAP_T, | |
1300 initialTexParams.fWrapT)); | |
1301 | 1504 |
1302 if (!this->uploadCompressedTexData(desc, idDesc.fInfo.fTarget, srcData)) { | 1505 if (!this->uploadCompressedTexData(desc, idDesc.fInfo.fTarget, texels)) { |
1303 GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID)); | 1506 GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID)); |
1304 return return_null_texture(); | 1507 return return_null_texture(); |
1305 } | 1508 } |
1306 | 1509 |
1307 GrGLTexture* tex; | 1510 GrGLTexture* tex; |
1308 tex = new GrGLTexture(this, desc, idDesc); | 1511 tex = new GrGLTexture(this, desc, idDesc); |
1309 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); | 1512 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); |
1310 #ifdef TRACE_TEXTURE_CREATION | 1513 #ifdef TRACE_TEXTURE_CREATION |
1311 SkDebugf("--- new compressed texture [%d] size=(%d %d) config=%d\n", | 1514 SkDebugf("--- new compressed texture [%d] size=(%d %d) config=%d\n", |
1312 glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig); | 1515 glTexDesc.fInfo.fID, desc.fWidth, desc.fHeight, desc.fConfig); |
1313 #endif | 1516 #endif |
1314 return tex; | 1517 return tex; |
1315 } | 1518 } |
1316 | 1519 |
1317 namespace { | 1520 namespace { |
1318 | 1521 |
1319 const GrGLuint kUnknownBitCount = GrGLStencilAttachment::kUnknownBitCount; | 1522 const GrGLuint kUnknownBitCount = GrGLStencilAttachment::kUnknownBitCount; |
1320 | 1523 |
1321 void inline get_stencil_rb_sizes(const GrGLInterface* gl, | 1524 void inline get_stencil_rb_sizes(const GrGLInterface* gl, |
1322 GrGLStencilAttachment::Format* format) { | 1525 GrGLStencilAttachment::Format* format) { |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1445 } | 1648 } |
1446 GL_CALL(DeleteTextures(1, &colorID)); | 1649 GL_CALL(DeleteTextures(1, &colorID)); |
1447 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, 0)); | 1650 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, 0)); |
1448 GL_CALL(DeleteFramebuffers(1, &fb)); | 1651 GL_CALL(DeleteFramebuffers(1, &fb)); |
1449 fGLContext->caps()->setStencilFormatIndexForConfig(config, firstWorkingS tencilFormatIndex); | 1652 fGLContext->caps()->setStencilFormatIndexForConfig(config, firstWorkingS tencilFormatIndex); |
1450 } | 1653 } |
1451 return this->glCaps().getStencilFormatIndexForConfig(config); | 1654 return this->glCaps().getStencilFormatIndexForConfig(config); |
1452 } | 1655 } |
1453 | 1656 |
1454 bool GrGLGpu::createTextureImpl(const GrSurfaceDesc& desc, GrGLTextureInfo* info , | 1657 bool GrGLGpu::createTextureImpl(const GrSurfaceDesc& desc, GrGLTextureInfo* info , |
1455 bool renderTarget, const void* srcData, | 1658 bool renderTarget, GrGLTexture::TexParams* initi alTexParams, |
1456 GrGLTexture::TexParams* initialTexParams, size_t rowBytes) { | 1659 const SkTArray<GrMipLevel>& texels) { |
1457 // Some drivers like to know filter/wrap before seeing glTexImage2D. Some | |
1458 // drivers have a bug where an FBO won't be complete if it includes a | |
1459 // texture that is not mipmap complete (considering the filter in use). | |
1460 | |
1461 // we only set a subset here so invalidate first | |
1462 initialTexParams->invalidate(); | |
1463 initialTexParams->fMinFilter = GR_GL_NEAREST; | |
1464 initialTexParams->fMagFilter = GR_GL_NEAREST; | |
1465 initialTexParams->fWrapS = GR_GL_CLAMP_TO_EDGE; | |
1466 initialTexParams->fWrapT = GR_GL_CLAMP_TO_EDGE; | |
1467 | |
1468 if (desc.fTextureStorageAllocator.fAllocateTextureStorage) { | 1660 if (desc.fTextureStorageAllocator.fAllocateTextureStorage) { |
1469 return this->createTextureExternalAllocatorImpl(desc, info, srcData, row Bytes); | 1661 return this->createTextureExternalAllocatorImpl(desc, info, texels); |
1470 } | 1662 } |
1471 | 1663 |
1472 info->fID = 0; | 1664 info->fID = 0; |
1473 info->fTarget = GR_GL_TEXTURE_2D; | 1665 info->fTarget = GR_GL_TEXTURE_2D; |
1474 GL_CALL(GenTextures(1, &(info->fID))); | 1666 GL_CALL(GenTextures(1, &(info->fID))); |
1475 | 1667 |
1476 if (!info->fID) { | 1668 if (!info->fID) { |
1477 return false; | 1669 return false; |
1478 } | 1670 } |
1479 | 1671 |
1480 this->setScratchTextureUnit(); | 1672 this->setScratchTextureUnit(); |
1481 GL_CALL(BindTexture(info->fTarget, info->fID)); | 1673 GL_CALL(BindTexture(info->fTarget, info->fID)); |
1482 | 1674 |
1483 if (renderTarget && this->glCaps().textureUsageSupport()) { | 1675 if (renderTarget && this->glCaps().textureUsageSupport()) { |
1484 // provides a hint about how this texture will be used | 1676 // provides a hint about how this texture will be used |
1485 GL_CALL(TexParameteri(info->fTarget, | 1677 GL_CALL(TexParameteri(info->fTarget, |
1486 GR_GL_TEXTURE_USAGE, | 1678 GR_GL_TEXTURE_USAGE, |
1487 GR_GL_FRAMEBUFFER_ATTACHMENT)); | 1679 GR_GL_FRAMEBUFFER_ATTACHMENT)); |
1488 } | 1680 } |
1489 | 1681 |
1490 GL_CALL(TexParameteri(info->fTarget, | 1682 if (info) { |
1491 GR_GL_TEXTURE_MAG_FILTER, | 1683 set_initial_texture_params(this->glInterface(), *info, initialTexParams) ; |
1492 initialTexParams->fMagFilter)); | 1684 } |
1493 GL_CALL(TexParameteri(info->fTarget, | |
1494 GR_GL_TEXTURE_MIN_FILTER, | |
1495 initialTexParams->fMinFilter)); | |
1496 GL_CALL(TexParameteri(info->fTarget, | |
1497 GR_GL_TEXTURE_WRAP_S, | |
1498 initialTexParams->fWrapS)); | |
1499 GL_CALL(TexParameteri(info->fTarget, | |
1500 GR_GL_TEXTURE_WRAP_T, | |
1501 initialTexParams->fWrapT)); | |
1502 if (!this->uploadTexData(desc, info->fTarget, kNewTexture_UploadType, 0, 0, | 1685 if (!this->uploadTexData(desc, info->fTarget, kNewTexture_UploadType, 0, 0, |
1503 desc.fWidth, desc.fHeight, | 1686 desc.fWidth, desc.fHeight, |
1504 desc.fConfig, srcData, rowBytes)) { | 1687 desc.fConfig, texels)) { |
1505 GL_CALL(DeleteTextures(1, &(info->fID))); | 1688 GL_CALL(DeleteTextures(1, &(info->fID))); |
1506 return false; | 1689 return false; |
1507 } | 1690 } |
1508 return true; | 1691 return true; |
1509 } | 1692 } |
1510 | 1693 |
1511 bool GrGLGpu::createTextureExternalAllocatorImpl( | 1694 bool GrGLGpu::createTextureExternalAllocatorImpl(const GrSurfaceDesc& desc, |
1512 const GrSurfaceDesc& desc, GrGLTextureInfo* info, const void* srcData, s ize_t rowBytes) { | 1695 GrGLTextureInfo* info, |
1696 const SkTArray<GrMipLevel>& tex els) { | |
1697 // We do not make SkTArray available outside of Skia, | |
1698 // and so we do not want to allow mipmaps to external | |
1699 // allocators just yet. | |
1700 SkASSERT(texels.count() == 1); | |
1701 SkSTArray<1, GrMipLevel> texelsShallowCopy(1); | |
1702 texelsShallowCopy.push_back(texels[0]); | |
1703 | |
1513 switch (desc.fTextureStorageAllocator.fAllocateTextureStorage( | 1704 switch (desc.fTextureStorageAllocator.fAllocateTextureStorage( |
1514 desc.fTextureStorageAllocator.fCtx, reinterpret_cast<GrBacke ndObject>(info), | 1705 desc.fTextureStorageAllocator.fCtx, reinterpret_cast<GrBacke ndObject>(info), |
1515 desc.fWidth, desc.fHeight, desc.fConfig, srcData, desc.fOrig in)) { | 1706 desc.fWidth, desc.fHeight, desc.fConfig, texelsShallowCopy[0 ].fPixels, |
1707 desc.fOrigin)) { | |
1516 case GrTextureStorageAllocator::Result::kSucceededAndUploaded: | 1708 case GrTextureStorageAllocator::Result::kSucceededAndUploaded: |
1517 return true; | 1709 return true; |
1518 case GrTextureStorageAllocator::Result::kFailed: | 1710 case GrTextureStorageAllocator::Result::kFailed: |
1519 return false; | 1711 return false; |
1520 case GrTextureStorageAllocator::Result::kSucceededWithoutUpload: | 1712 case GrTextureStorageAllocator::Result::kSucceededWithoutUpload: |
1521 break; | 1713 break; |
1522 } | 1714 } |
1523 | 1715 |
1524 if (!this->uploadTexData(desc, info->fTarget, kNewTexture_UploadType, 0, 0, | 1716 if (!this->uploadTexData(desc, info->fTarget, kNewTexture_UploadType, 0, 0, |
1525 desc.fWidth, desc.fHeight, | 1717 desc.fWidth, desc.fHeight, |
1526 desc.fConfig, srcData, rowBytes)) { | 1718 desc.fConfig, texelsShallowCopy)) { |
1527 desc.fTextureStorageAllocator.fDeallocateTextureStorage( | 1719 desc.fTextureStorageAllocator.fDeallocateTextureStorage( |
1528 desc.fTextureStorageAllocator.fCtx, reinterpret_cast<GrBackendOb ject>(info)); | 1720 desc.fTextureStorageAllocator.fCtx, reinterpret_cast<GrBackendOb ject>(info)); |
1529 return false; | 1721 return false; |
1530 } | 1722 } |
1531 return true; | 1723 return true; |
1532 } | 1724 } |
1533 | 1725 |
1534 GrStencilAttachment* GrGLGpu::createStencilAttachmentForRenderTarget(const GrRen derTarget* rt, | 1726 GrStencilAttachment* GrGLGpu::createStencilAttachmentForRenderTarget(const GrRen derTarget* rt, |
1535 int width, | 1727 int width, |
1536 int height) { | 1728 int height) { |
(...skipping 1438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2975 | 3167 |
2976 if (GrTextureParams::kMipMap_FilterMode == filterMode) { | 3168 if (GrTextureParams::kMipMap_FilterMode == filterMode) { |
2977 if (!this->caps()->mipMapSupport() || GrPixelConfigIsCompressed(texture- >config())) { | 3169 if (!this->caps()->mipMapSupport() || GrPixelConfigIsCompressed(texture- >config())) { |
2978 filterMode = GrTextureParams::kBilerp_FilterMode; | 3170 filterMode = GrTextureParams::kBilerp_FilterMode; |
2979 } | 3171 } |
2980 } | 3172 } |
2981 | 3173 |
2982 newTexParams.fMinFilter = glMinFilterModes[filterMode]; | 3174 newTexParams.fMinFilter = glMinFilterModes[filterMode]; |
2983 newTexParams.fMagFilter = glMagFilterModes[filterMode]; | 3175 newTexParams.fMagFilter = glMagFilterModes[filterMode]; |
2984 | 3176 |
2985 if (GrTextureParams::kMipMap_FilterMode == filterMode && | 3177 if (GrTextureParams::kMipMap_FilterMode == filterMode) { |
2986 texture->texturePriv().mipMapsAreDirty()) { | 3178 if (texture->texturePriv().mipMapsAreDirty()) { |
2987 GL_CALL(GenerateMipmap(target)); | 3179 GL_CALL(GenerateMipmap(target)); |
2988 texture->texturePriv().dirtyMipMaps(false); | 3180 texture->texturePriv().dirtyMipMaps(false); |
3181 texture->texturePriv().setMaxMipMapLevel(SkMipMap::ComputeLevelCount ( | |
3182 texture->width(), texture->height())); | |
3183 } | |
2989 } | 3184 } |
2990 | 3185 |
3186 newTexParams.fMaxMipMapLevel = texture->texturePriv().maxMipMapLevel(); | |
3187 | |
2991 newTexParams.fWrapS = tile_to_gl_wrap(params.getTileModeX()); | 3188 newTexParams.fWrapS = tile_to_gl_wrap(params.getTileModeX()); |
2992 newTexParams.fWrapT = tile_to_gl_wrap(params.getTileModeY()); | 3189 newTexParams.fWrapT = tile_to_gl_wrap(params.getTileModeY()); |
2993 get_tex_param_swizzle(texture->config(), this->glCaps(), newTexParams.fSwizz leRGBA); | 3190 get_tex_param_swizzle(texture->config(), this->glCaps(), newTexParams.fSwizz leRGBA); |
2994 if (setAll || newTexParams.fMagFilter != oldTexParams.fMagFilter) { | 3191 if (setAll || newTexParams.fMagFilter != oldTexParams.fMagFilter) { |
2995 this->setTextureUnit(unitIdx); | 3192 this->setTextureUnit(unitIdx); |
2996 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAG_FILTER, newTexParams.fMa gFilter)); | 3193 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAG_FILTER, newTexParams.fMa gFilter)); |
2997 } | 3194 } |
2998 if (setAll || newTexParams.fMinFilter != oldTexParams.fMinFilter) { | 3195 if (setAll || newTexParams.fMinFilter != oldTexParams.fMinFilter) { |
2999 this->setTextureUnit(unitIdx); | 3196 this->setTextureUnit(unitIdx); |
3000 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_FILTER, newTexParams.fMi nFilter)); | 3197 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_FILTER, newTexParams.fMi nFilter)); |
3001 } | 3198 } |
3199 if (setAll || newTexParams.fMaxMipMapLevel != oldTexParams.fMaxMipMapLevel) { | |
3200 if (newTexParams.fMaxMipMapLevel != 0) { | |
3201 this->setTextureUnit(unitIdx); | |
3202 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_LOD, 0)); | |
3203 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_BASE_LEVEL, 0)); | |
3204 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAX_LOD, | |
3205 newTexParams.fMaxMipMapLevel)); | |
3206 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAX_LEVEL, | |
3207 newTexParams.fMaxMipMapLevel)); | |
3208 } | |
3209 } | |
3002 if (setAll || newTexParams.fWrapS != oldTexParams.fWrapS) { | 3210 if (setAll || newTexParams.fWrapS != oldTexParams.fWrapS) { |
3003 this->setTextureUnit(unitIdx); | 3211 this->setTextureUnit(unitIdx); |
3004 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_S, newTexParams.fWrapS) ); | 3212 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_S, newTexParams.fWrapS) ); |
3005 } | 3213 } |
3006 if (setAll || newTexParams.fWrapT != oldTexParams.fWrapT) { | 3214 if (setAll || newTexParams.fWrapT != oldTexParams.fWrapT) { |
3007 this->setTextureUnit(unitIdx); | 3215 this->setTextureUnit(unitIdx); |
3008 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_T, newTexParams.fWrapT) ); | 3216 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_T, newTexParams.fWrapT) ); |
3009 } | 3217 } |
3010 if (this->glCaps().textureSwizzleSupport() && | 3218 if (this->glCaps().textureSwizzleSupport() && |
3011 (setAll || memcmp(newTexParams.fSwizzleRGBA, | 3219 (setAll || memcmp(newTexParams.fSwizzleRGBA, |
(...skipping 940 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3952 if (GR_GL_TEXTURE_EXTERNAL == glTexture->target() || | 4160 if (GR_GL_TEXTURE_EXTERNAL == glTexture->target() || |
3953 GR_GL_TEXTURE_RECTANGLE == glTexture->target()) { | 4161 GR_GL_TEXTURE_RECTANGLE == glTexture->target()) { |
3954 copyParams->fFilter = GrTextureParams::kNone_FilterMode; | 4162 copyParams->fFilter = GrTextureParams::kNone_FilterMode; |
3955 copyParams->fWidth = texture->width(); | 4163 copyParams->fWidth = texture->width(); |
3956 copyParams->fHeight = texture->height(); | 4164 copyParams->fHeight = texture->height(); |
3957 return true; | 4165 return true; |
3958 } | 4166 } |
3959 } | 4167 } |
3960 return false; | 4168 return false; |
3961 } | 4169 } |
OLD | NEW |