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) |
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
548 #endif | 551 #endif |
549 | 552 |
550 // next line relies on GrBackendTextureDesc's flags matching GrTexture's | 553 // next line relies on GrBackendTextureDesc's flags matching GrTexture's |
551 bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFla
g); | 554 bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFla
g); |
552 | 555 |
553 GrGLTexture::IDDesc idDesc; | 556 GrGLTexture::IDDesc idDesc; |
554 GrSurfaceDesc surfDesc; | 557 GrSurfaceDesc surfDesc; |
555 | 558 |
556 #ifdef SK_IGNORE_GL_TEXTURE_TARGET | 559 #ifdef SK_IGNORE_GL_TEXTURE_TARGET |
557 idDesc.fInfo.fID = static_cast<GrGLuint>(desc.fTextureHandle); | 560 idDesc.fInfo.fID = static_cast<GrGLuint>(desc.fTextureHandle); |
558 // We only support GL_TEXTURE_2D at the moment. | 561 // When we create the texture, we only |
| 562 // create GL_TEXTURE_2D at the moment. |
| 563 // External clients can do something different. |
| 564 |
559 idDesc.fInfo.fTarget = GR_GL_TEXTURE_2D; | 565 idDesc.fInfo.fTarget = GR_GL_TEXTURE_2D; |
560 #else | 566 #else |
561 idDesc.fInfo = *info; | 567 idDesc.fInfo = *info; |
562 #endif | 568 #endif |
563 | 569 |
564 if (GR_GL_TEXTURE_EXTERNAL == idDesc.fInfo.fTarget) { | 570 if (GR_GL_TEXTURE_EXTERNAL == idDesc.fInfo.fTarget) { |
565 if (renderTarget) { | 571 if (renderTarget) { |
566 // This combination is not supported. | 572 // This combination is not supported. |
567 return nullptr; | 573 return nullptr; |
568 } | 574 } |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
802 // Write or transfer of pixels is not implemented for TEXTURE_EXTERNAL textu
res | 808 // Write or transfer of pixels is not implemented for TEXTURE_EXTERNAL textu
res |
803 if (GR_GL_TEXTURE_EXTERNAL == glTex->target()) { | 809 if (GR_GL_TEXTURE_EXTERNAL == glTex->target()) { |
804 return false; | 810 return false; |
805 } | 811 } |
806 | 812 |
807 return true; | 813 return true; |
808 } | 814 } |
809 | 815 |
810 bool GrGLGpu::onWritePixels(GrSurface* surface, | 816 bool GrGLGpu::onWritePixels(GrSurface* surface, |
811 int left, int top, int width, int height, | 817 int left, int top, int width, int height, |
812 GrPixelConfig config, const void* buffer, | 818 GrPixelConfig config, |
813 size_t rowBytes) { | 819 const SkTArray<GrMipLevel>& texels) { |
814 GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture()); | 820 GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture()); |
815 | 821 |
816 if (!check_write_and_transfer_input(glTex, surface, config)) { | 822 if (!check_write_and_transfer_input(glTex, surface, config)) { |
817 return false; | 823 return false; |
818 } | 824 } |
819 | 825 |
820 this->setScratchTextureUnit(); | 826 this->setScratchTextureUnit(); |
821 GL_CALL(BindTexture(glTex->target(), glTex->textureID())); | 827 GL_CALL(BindTexture(glTex->target(), glTex->textureID())); |
822 | 828 |
823 bool success = false; | 829 bool success = false; |
824 if (GrPixelConfigIsCompressed(glTex->desc().fConfig)) { | 830 if (GrPixelConfigIsCompressed(glTex->desc().fConfig)) { |
825 // We check that config == desc.fConfig in GrGLGpu::canWriteTexturePixel
s() | 831 // We check that config == desc.fConfig in GrGLGpu::canWriteTexturePixel
s() |
826 SkASSERT(config == glTex->desc().fConfig); | 832 SkASSERT(config == glTex->desc().fConfig); |
827 success = this->uploadCompressedTexData(glTex->desc(), glTex->target(),
buffer, | 833 success = this->uploadCompressedTexData(glTex->desc(), glTex->target(),
texels, |
828 kWrite_UploadType, left, top, wi
dth, height); | 834 kWrite_UploadType, left, top, wi
dth, height); |
829 } else { | 835 } else { |
830 success = this->uploadTexData(glTex->desc(), glTex->target(), kWrite_Upl
oadType, | 836 success = this->uploadTexData(glTex->desc(), glTex->target(), kWrite_Upl
oadType, |
831 left, top, width, height, config, buffer,
rowBytes); | 837 left, top, width, height, config, texels); |
832 } | 838 } |
833 | 839 |
834 if (success) { | 840 return success; |
835 glTex->texturePriv().dirtyMipMaps(true); | |
836 return true; | |
837 } | |
838 | |
839 return false; | |
840 } | 841 } |
841 | 842 |
842 bool GrGLGpu::onTransferPixels(GrSurface* surface, | 843 bool GrGLGpu::onTransferPixels(GrSurface* surface, |
843 int left, int top, int width, int height, | 844 int left, int top, int width, int height, |
844 GrPixelConfig config, GrTransferBuffer* buffer, | 845 GrPixelConfig config, GrTransferBuffer* buffer, |
845 size_t offset, size_t rowBytes) { | 846 size_t offset, size_t rowBytes) { |
846 GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture()); | 847 GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture()); |
847 | 848 |
848 if (!check_write_and_transfer_input(glTex, surface, config)) { | 849 if (!check_write_and_transfer_input(glTex, surface, config)) { |
849 return false; | 850 return false; |
850 } | 851 } |
851 | 852 |
852 // For the moment, can't transfer compressed data | 853 // For the moment, can't transfer compressed data |
853 if (GrPixelConfigIsCompressed(glTex->desc().fConfig)) { | 854 if (GrPixelConfigIsCompressed(glTex->desc().fConfig)) { |
854 return false; | 855 return false; |
855 } | 856 } |
856 | 857 |
857 this->setScratchTextureUnit(); | 858 this->setScratchTextureUnit(); |
858 GL_CALL(BindTexture(glTex->target(), glTex->textureID())); | 859 GL_CALL(BindTexture(glTex->target(), glTex->textureID())); |
859 | 860 |
860 SkASSERT(!buffer->isMapped()); | 861 SkASSERT(!buffer->isMapped()); |
861 GrGLTransferBuffer* glBuffer = reinterpret_cast<GrGLTransferBuffer*>(buffer)
; | 862 GrGLTransferBuffer* glBuffer = reinterpret_cast<GrGLTransferBuffer*>(buffer)
; |
862 // bind the transfer buffer | 863 // bind the transfer buffer |
863 SkASSERT(GR_GL_PIXEL_UNPACK_BUFFER == glBuffer->bufferType() || | 864 SkASSERT(GR_GL_PIXEL_UNPACK_BUFFER == glBuffer->bufferType() || |
864 GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM == glBuffer->bufferType
()); | 865 GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM == glBuffer->bufferType
()); |
865 GL_CALL(BindBuffer(glBuffer->bufferType(), glBuffer->bufferID())); | 866 GL_CALL(BindBuffer(glBuffer->bufferType(), glBuffer->bufferID())); |
866 | 867 |
867 bool success = false; | 868 bool success = false; |
| 869 GrMipLevel mipLevel; |
| 870 mipLevel.fPixels = buffer; |
| 871 mipLevel.fRowBytes = rowBytes; |
| 872 SkSTArray<1, GrMipLevel> texels; |
| 873 texels.push_back(mipLevel); |
868 success = this->uploadTexData(glTex->desc(), glTex->target(), kTransfer_Uplo
adType, | 874 success = this->uploadTexData(glTex->desc(), glTex->target(), kTransfer_Uplo
adType, |
869 left, top, width, height, config, buffer, rowB
ytes); | 875 left, top, width, height, config, texels); |
870 | |
871 if (success) { | 876 if (success) { |
872 glTex->texturePriv().dirtyMipMaps(true); | 877 glTex->texturePriv().dirtyMipMaps(true); |
873 return true; | 878 return true; |
874 } | 879 } |
875 | 880 |
876 return false; | 881 return false; |
877 } | 882 } |
878 | 883 |
879 // For GL_[UN]PACK_ALIGNMENT. | 884 // For GL_[UN]PACK_ALIGNMENT. |
880 static inline GrGLint config_alignment(GrPixelConfig config) { | 885 static inline GrGLint config_alignment(GrPixelConfig config) { |
(...skipping 18 matching lines...) Expand all Loading... |
899 | 904 |
900 static inline GrGLenum check_alloc_error(const GrSurfaceDesc& desc, | 905 static inline GrGLenum check_alloc_error(const GrSurfaceDesc& desc, |
901 const GrGLInterface* interface) { | 906 const GrGLInterface* interface) { |
902 if (SkToBool(desc.fFlags & kCheckAllocation_GrSurfaceFlag)) { | 907 if (SkToBool(desc.fFlags & kCheckAllocation_GrSurfaceFlag)) { |
903 return GR_GL_GET_ERROR(interface); | 908 return GR_GL_GET_ERROR(interface); |
904 } else { | 909 } else { |
905 return CHECK_ALLOC_ERROR(interface); | 910 return CHECK_ALLOC_ERROR(interface); |
906 } | 911 } |
907 } | 912 } |
908 | 913 |
| 914 /** |
| 915 * Creates storage space for the texture and fills it with texels. |
| 916 * |
| 917 * @param desc The surface descriptor for the texture being created. |
| 918 * @param interface The GL interface in use. |
| 919 * @param target The GL target to which the texture is bound |
| 920 * @param internalFormat The data format used for the internal storage of the te
xture. |
| 921 * @param externalFormat The data format used for the external storage of the te
xture. |
| 922 * @param externalType The type of the data used for the external storage of t
he texture. |
| 923 * @param texels The texel data of the texture being created. |
| 924 * @param baseWidth The width of the texture's base mipmap level |
| 925 * @param baseHeight The height of the texture's base mipmap level |
| 926 * @param succeeded Set to true if allocating and populating the texture co
mpleted |
| 927 * without error. |
| 928 */ |
| 929 static void allocate_and_populate_uncompressed_texture(const GrSurfaceDesc& desc
, |
| 930 const GrGLInterface& inte
rface, |
| 931 GrGLenum target, |
| 932 GrGLenum internalFormat, |
| 933 GrGLenum externalFormat, |
| 934 GrGLenum externalType, |
| 935 const SkTArray<GrMipLevel
>& texels, |
| 936 int baseWidth, int baseHe
ight, |
| 937 bool* succeeded) { |
| 938 CLEAR_ERROR_BEFORE_ALLOC(&interface); |
| 939 *succeeded = true; |
| 940 for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLe
vel++) { |
| 941 int twoToTheMipLevel = 1 << currentMipLevel; |
| 942 int currentWidth = SkTMax(1, baseWidth / twoToTheMipLevel); |
| 943 int currentHeight = SkTMax(1, baseHeight / twoToTheMipLevel); |
| 944 const void* currentMipData = texels[currentMipLevel].fPixels; |
| 945 // Even if curremtMipData is nullptr, continue to call TexImage2D. |
| 946 // This will allocate texture memory which we can later populate. |
| 947 GL_ALLOC_CALL(&interface, |
| 948 TexImage2D(target, |
| 949 currentMipLevel, |
| 950 internalFormat, |
| 951 currentWidth, |
| 952 currentHeight, |
| 953 0, // border |
| 954 externalFormat, externalType, |
| 955 currentMipData)); |
| 956 GrGLenum error = check_alloc_error(desc, &interface); |
| 957 if (error != GR_GL_NO_ERROR) { |
| 958 *succeeded = false; |
| 959 break; |
| 960 } |
| 961 } |
| 962 } |
| 963 |
| 964 /** |
| 965 * Creates storage space for the texture and fills it with texels. |
| 966 * |
| 967 * @param desc The surface descriptor for the texture being created. |
| 968 * @param interface The GL interface in use. |
| 969 * @param target The GL target to which the texture is bound |
| 970 * @param internalFormat The data format used for the internal storage of the te
xture. |
| 971 * @param texels The texel data of the texture being created. |
| 972 * @param baseWidth The width of the texture's base mipmap level |
| 973 * @param baseHeight The height of the texture's base mipmap level |
| 974 */ |
| 975 static bool allocate_and_populate_compressed_texture(const GrSurfaceDesc& desc, |
| 976 const GrGLInterface& interf
ace, |
| 977 GrGLenum target, GrGLenum i
nternalFormat, |
| 978 const SkTArray<GrMipLevel>&
texels, |
| 979 int baseWidth, int baseHeig
ht) { |
| 980 CLEAR_ERROR_BEFORE_ALLOC(&interface); |
| 981 for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLe
vel++) { |
| 982 int twoToTheMipLevel = 1 << currentMipLevel; |
| 983 int currentWidth = SkTMax(1, baseWidth / twoToTheMipLevel); |
| 984 int currentHeight = SkTMax(1, baseHeight / twoToTheMipLevel); |
| 985 |
| 986 // Make sure that the width and height that we pass to OpenGL |
| 987 // is a multiple of the block size. |
| 988 size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, baseWidth, ba
seHeight); |
| 989 |
| 990 GL_ALLOC_CALL(&interface, |
| 991 CompressedTexImage2D(target, |
| 992 currentMipLevel, |
| 993 internalFormat, |
| 994 currentWidth, |
| 995 currentHeight, |
| 996 0, // border |
| 997 SkToInt(dataSize), |
| 998 texels[currentMipLevel].fPixels)); |
| 999 |
| 1000 GrGLenum error = check_alloc_error(desc, &interface); |
| 1001 if (error != GR_GL_NO_ERROR) { |
| 1002 return false; |
| 1003 } |
| 1004 } |
| 1005 |
| 1006 return true; |
| 1007 } |
| 1008 |
| 1009 /** |
| 1010 * After a texture is created, any state which was altered during its creation |
| 1011 * needs to be restored. |
| 1012 * |
| 1013 * @param interface The GL interface to use. |
| 1014 * @param caps The capabilities of the GL device. |
| 1015 * @param restoreGLRowLength Should the row length unpacking be restored? |
| 1016 * @param glFlipY Did GL flip the texture vertically? |
| 1017 */ |
| 1018 static void restore_pixelstore_state(const GrGLInterface& interface, const GrGLC
aps& caps, |
| 1019 bool restoreGLRowLength, bool glFlipY) { |
| 1020 if (restoreGLRowLength) { |
| 1021 SkASSERT(caps.unpackRowLengthSupport()); |
| 1022 GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0)); |
| 1023 } |
| 1024 if (glFlipY) { |
| 1025 GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE)); |
| 1026 } |
| 1027 } |
| 1028 |
909 bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc, | 1029 bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc, |
910 GrGLenum target, | 1030 GrGLenum target, |
911 UploadType uploadType, | 1031 UploadType uploadType, |
912 int left, int top, int width, int height, | 1032 int left, int top, int width, int height, |
913 GrPixelConfig dataConfig, | 1033 GrPixelConfig dataConfig, |
914 const void* dataOrOffset, | 1034 const SkTArray<GrMipLevel>& texels) { |
915 size_t rowBytes) { | |
916 SkASSERT(dataOrOffset || kNewTexture_UploadType == uploadType || | |
917 kTransfer_UploadType == uploadType); | |
918 | |
919 // If we're uploading compressed data then we should be using uploadCompress
edTexData | 1035 // If we're uploading compressed data then we should be using uploadCompress
edTexData |
920 SkASSERT(!GrPixelConfigIsCompressed(dataConfig)); | 1036 SkASSERT(!GrPixelConfigIsCompressed(dataConfig)); |
921 | 1037 |
922 SkASSERT(this->caps()->isConfigTexturable(desc.fConfig)); | 1038 SkASSERT(this->caps()->isConfigTexturable(desc.fConfig)); |
923 | 1039 |
| 1040 // texels is const. |
| 1041 // But we may need to flip the texture vertically to prepare it. |
| 1042 // Rather than flip in place and alter the incoming data, |
| 1043 // we allocate a new buffer to flip into. |
| 1044 // This means we need to make a non-const shallow copy of texels. |
| 1045 SkTArray<GrMipLevel> texelsShallowCopy(texels); |
| 1046 |
| 1047 for (int currentMipLevel = texelsShallowCopy.count() - 1; currentMipLevel >=
0; |
| 1048 currentMipLevel--) { |
| 1049 SkASSERT(texelsShallowCopy[currentMipLevel].fPixels || |
| 1050 kNewTexture_UploadType == uploadType || kTransfer_UploadType ==
uploadType); |
| 1051 } |
| 1052 |
| 1053 const GrGLInterface* interface = this->glInterface(); |
| 1054 const GrGLCaps& caps = this->glCaps(); |
| 1055 |
924 size_t bpp = GrBytesPerPixel(dataConfig); | 1056 size_t bpp = GrBytesPerPixel(dataConfig); |
925 if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, &
left, &top, | 1057 |
926 &width, &height, &dataOrOffset, &
rowBytes)) { | 1058 if (width == 0 || height == 0) { |
927 return false; | 1059 return false; |
928 } | 1060 } |
929 size_t trimRowBytes = width * bpp; | |
930 | 1061 |
931 // in case we need a temporary, trimmed copy of the src pixels | 1062 for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); c
urrentMipLevel++) { |
932 SkAutoSMalloc<128 * 128> tempStorage; | 1063 int twoToTheMipLevel = 1 << currentMipLevel; |
| 1064 int currentWidth = SkTMax(1, width / twoToTheMipLevel); |
| 1065 int currentHeight = SkTMax(1, height / twoToTheMipLevel); |
| 1066 |
| 1067 if (texelsShallowCopy[currentMipLevel].fPixels == nullptr) { |
| 1068 continue; |
| 1069 } |
| 1070 |
| 1071 if (currentHeight > SK_MaxS32 || |
| 1072 currentWidth > SK_MaxS32) { |
| 1073 return false; |
| 1074 } |
| 1075 if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bp
p, &left, &top, |
| 1076 ¤tWidth, |
| 1077 ¤tHeight, |
| 1078 &texelsShallowCopy[currentMipLeve
l].fPixels, |
| 1079 &texelsShallowCopy[currentMipLeve
l].fRowBytes)) { |
| 1080 return false; |
| 1081 } |
| 1082 if (currentWidth < 0 || currentHeight < 0) { |
| 1083 return false; |
| 1084 } |
| 1085 } |
933 | 1086 |
934 // Internal format comes from the texture desc. | 1087 // Internal format comes from the texture desc. |
935 GrGLenum internalFormat; | 1088 GrGLenum internalFormat; |
936 // External format and type come from the upload data. | 1089 // External format and type come from the upload data. |
937 GrGLenum externalFormat; | 1090 GrGLenum externalFormat; |
938 GrGLenum externalType; | 1091 GrGLenum externalType; |
939 if (!this->glCaps().getTexImageFormats(desc.fConfig, dataConfig, &internalFo
rmat, | 1092 if (!this->glCaps().getTexImageFormats(desc.fConfig, dataConfig, &internalFo
rmat, |
940 &externalFormat, &externalType)) { | 1093 &externalFormat, &externalType)) { |
941 return false; | 1094 return false; |
942 } | 1095 } |
943 /* | 1096 /* |
944 * Check whether to allocate a temporary buffer for flipping y or | 1097 * Check whether to allocate a temporary buffer for flipping y or |
945 * because our srcData has extra bytes past each row. If so, we need | 1098 * because our srcData has extra bytes past each row. If so, we need |
946 * to trim those off here, since GL ES may not let us specify | 1099 * to trim those off here, since GL ES may not let us specify |
947 * GL_UNPACK_ROW_LENGTH. | 1100 * GL_UNPACK_ROW_LENGTH. |
948 */ | 1101 */ |
949 bool restoreGLRowLength = false; | 1102 bool restoreGLRowLength = false; |
950 bool swFlipY = false; | 1103 bool swFlipY = false; |
951 bool glFlipY = false; | 1104 bool glFlipY = false; |
952 if (dataOrOffset) { | 1105 |
953 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { | 1106 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { |
954 if (this->glCaps().unpackFlipYSupport()) { | 1107 if (caps.unpackFlipYSupport()) { |
955 glFlipY = true; | 1108 glFlipY = true; |
956 } else { | 1109 } else { |
957 swFlipY = true; | 1110 swFlipY = true; |
958 } | |
959 } | 1111 } |
960 if (this->glCaps().unpackRowLengthSupport() && !swFlipY) { | 1112 } |
| 1113 |
| 1114 // in case we need a temporary, trimmed copy of the src pixels |
| 1115 SkAutoSMalloc<128 * 128> tempStorage; |
| 1116 |
| 1117 // find the combined size of all the mip levels and the relative offset of |
| 1118 // each into the collective buffer |
| 1119 size_t combined_buffer_size = 0; |
| 1120 SkTArray<size_t> individual_mip_offsets(texelsShallowCopy.count()); |
| 1121 for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); c
urrentMipLevel++) { |
| 1122 int twoToTheMipLevel = 1 << currentMipLevel; |
| 1123 int currentWidth = SkTMax(1, width / twoToTheMipLevel); |
| 1124 int currentHeight = SkTMax(1, height / twoToTheMipLevel); |
| 1125 const size_t trimmedSize = currentWidth * bpp * currentHeight; |
| 1126 individual_mip_offsets.push_back(combined_buffer_size); |
| 1127 combined_buffer_size += trimmedSize; |
| 1128 } |
| 1129 char* buffer = (char*)tempStorage.reset(combined_buffer_size); |
| 1130 |
| 1131 for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); c
urrentMipLevel++) { |
| 1132 if (texelsShallowCopy[currentMipLevel].fPixels == nullptr) { |
| 1133 continue; |
| 1134 } |
| 1135 |
| 1136 int twoToTheMipLevel = 1 << currentMipLevel; |
| 1137 int currentWidth = SkTMax(1, width / twoToTheMipLevel); |
| 1138 int currentHeight = SkTMax(1, height / twoToTheMipLevel); |
| 1139 const size_t trimRowBytes = currentWidth * bpp; |
| 1140 |
| 1141 /* |
| 1142 * check whether to allocate a temporary buffer for flipping y or |
| 1143 * because our srcData has extra bytes past each row. If so, we need |
| 1144 * to trim those off here, since GL ES may not let us specify |
| 1145 * GL_UNPACK_ROW_LENGTH. |
| 1146 */ |
| 1147 restoreGLRowLength = false; |
| 1148 |
| 1149 const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes; |
| 1150 if (caps.unpackRowLengthSupport() && !swFlipY) { |
961 // can't use this for flipping, only non-neg values allowed. :( | 1151 // can't use this for flipping, only non-neg values allowed. :( |
962 if (rowBytes != trimRowBytes) { | 1152 if (rowBytes != trimRowBytes) { |
963 GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp); | 1153 GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp); |
964 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength)); | 1154 GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLe
ngth)); |
965 restoreGLRowLength = true; | 1155 restoreGLRowLength = true; |
966 } | 1156 } |
967 } else if (kTransfer_UploadType != uploadType) { | 1157 } else if (kTransfer_UploadType != uploadType) { |
968 if (trimRowBytes != rowBytes || swFlipY) { | 1158 if (trimRowBytes != rowBytes || swFlipY) { |
969 // copy data into our new storage, skipping the trailing bytes | 1159 // copy data into our new storage, skipping the trailing bytes |
970 size_t trimSize = height * trimRowBytes; | 1160 const char* src = (const char*)texelsShallowCopy[currentMipLevel
].fPixels; |
971 const char* src = (const char*)dataOrOffset; | 1161 if (swFlipY && currentHeight >= 1) { |
972 if (swFlipY) { | 1162 src += (currentHeight - 1) * rowBytes; |
973 src += (height - 1) * rowBytes; | |
974 } | 1163 } |
975 char* dst = (char*)tempStorage.reset(trimSize); | 1164 char* dst = buffer + individual_mip_offsets[currentMipLevel]; |
976 for (int y = 0; y < height; y++) { | 1165 for (int y = 0; y < currentHeight; y++) { |
977 memcpy(dst, src, trimRowBytes); | 1166 memcpy(dst, src, trimRowBytes); |
978 if (swFlipY) { | 1167 if (swFlipY) { |
979 src -= rowBytes; | 1168 src -= rowBytes; |
980 } else { | 1169 } else { |
981 src += rowBytes; | 1170 src += rowBytes; |
982 } | 1171 } |
983 dst += trimRowBytes; | 1172 dst += trimRowBytes; |
984 } | 1173 } |
985 // now point data to our copied version | 1174 // now point data to our copied version |
986 dataOrOffset = tempStorage.get(); | 1175 texelsShallowCopy[currentMipLevel].fPixels = buffer + |
| 1176 individual_mip_offsets[currentMipLevel]; |
| 1177 texelsShallowCopy[currentMipLevel].fRowBytes = trimRowBytes; |
987 } | 1178 } |
988 } else { | 1179 } else { |
989 return false; | 1180 return false; |
990 } | 1181 } |
991 if (glFlipY) { | 1182 if (glFlipY) { |
992 GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE)); | 1183 GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE)); |
993 } | 1184 } |
994 GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, config_alignment(dataConfig)
)); | 1185 GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ALIGNMENT, |
| 1186 config_alignment(desc.fConfig))); |
995 } | 1187 } |
| 1188 |
996 bool succeeded = true; | 1189 bool succeeded = true; |
997 if (kNewTexture_UploadType == uploadType) { | 1190 if (kNewTexture_UploadType == uploadType && |
998 if (dataOrOffset && | 1191 0 == left && 0 == top && |
999 !(0 == left && 0 == top && desc.fWidth == width && desc.fHeight == h
eight)) { | 1192 desc.fWidth == width && desc.fHeight == height && |
1000 succeeded = false; | 1193 !desc.fTextureStorageAllocator.fAllocateTextureStorage) { |
1001 } else { | 1194 allocate_and_populate_uncompressed_texture(desc, *interface, target, |
1002 if (desc.fTextureStorageAllocator.fAllocateTextureStorage) { | 1195 internalFormat, externalForma
t, |
1003 if (dataOrOffset) { | 1196 externalType, texelsShallowCo
py, |
1004 GL_CALL(TexSubImage2D(target, | 1197 width, height, &succeeded); |
1005 0, // level | |
1006 left, top, | |
1007 width, height, | |
1008 externalFormat, externalType, dataOrOf
fset)); | |
1009 } | |
1010 } else {
| |
1011 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
| |
1012 GL_ALLOC_CALL(this->glInterface(), TexImage2D(
| |
1013 target, 0, internalFormat, desc.fWidth, desc.fHeight, 0, ext
ernalFormat, | |
1014 externalType, dataOrOffset));
| |
1015 GrGLenum error = check_alloc_error(desc, this->glInterface()); | |
1016 if (error != GR_GL_NO_ERROR) {
| |
1017 succeeded = false;
| |
1018 } | |
1019 } | |
1020 } | |
1021 } else { | 1198 } else { |
1022 if (swFlipY || glFlipY) { | 1199 if (swFlipY || glFlipY) { |
1023 top = desc.fHeight - (top + height); | 1200 top = desc.fHeight - (top + height); |
1024 } | 1201 } |
1025 GL_CALL(TexSubImage2D(target, | 1202 for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(
); |
1026 0, // level | 1203 currentMipLevel++) { |
1027 left, top, | 1204 int twoToTheMipLevel = 1 << currentMipLevel; |
1028 width, height, | 1205 int currentWidth = SkTMax(1, width / twoToTheMipLevel); |
1029 externalFormat, externalType, dataOrOffset)); | 1206 int currentHeight = SkTMax(1, height / twoToTheMipLevel); |
| 1207 if (texelsShallowCopy[currentMipLevel].fPixels == nullptr) { |
| 1208 continue; |
| 1209 } |
| 1210 |
| 1211 GL_CALL(TexSubImage2D(target, |
| 1212 currentMipLevel, |
| 1213 left, top, |
| 1214 currentWidth, |
| 1215 currentHeight, |
| 1216 externalFormat, externalType, |
| 1217 texelsShallowCopy[currentMipLevel].fPixels)); |
| 1218 } |
1030 } | 1219 } |
1031 | 1220 |
1032 if (restoreGLRowLength) { | 1221 restore_pixelstore_state(*interface, caps, restoreGLRowLength, glFlipY); |
1033 SkASSERT(this->glCaps().unpackRowLengthSupport()); | 1222 |
1034 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0)); | |
1035 } | |
1036 if (glFlipY) { | |
1037 GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE)); | |
1038 } | |
1039 return succeeded; | 1223 return succeeded; |
1040 } | 1224 } |
1041 | 1225 |
1042 // TODO: This function is using a lot of wonky semantics like, if width == -1 | 1226 // TODO: This function is using a lot of wonky semantics like, if width == -1 |
1043 // then set width = desc.fWdith ... blah. A better way to do it might be to | 1227 // then set width = desc.fWdith ... blah. A better way to do it might be to |
1044 // create a CompressedTexData struct that takes a desc/ptr and figures out | 1228 // create a CompressedTexData struct that takes a desc/ptr and figures out |
1045 // the proper upload semantics. Then users can construct this function how they | 1229 // the proper upload semantics. Then users can construct this function how they |
1046 // see fit if they want to go against the "standard" way to do it. | 1230 // see fit if they want to go against the "standard" way to do it. |
1047 bool GrGLGpu::uploadCompressedTexData(const GrSurfaceDesc& desc, | 1231 bool GrGLGpu::uploadCompressedTexData(const GrSurfaceDesc& desc, |
1048 GrGLenum target, | 1232 GrGLenum target, |
1049 const void* data, | 1233 const SkTArray<GrMipLevel>& texels, |
1050 UploadType uploadType, | 1234 UploadType uploadType, |
1051 int left, int top, int width, int height)
{ | 1235 int left, int top, int width, int height)
{ |
1052 SkASSERT(this->caps()->isConfigTexturable(desc.fConfig)); | 1236 SkASSERT(this->caps()->isConfigTexturable(desc.fConfig)); |
1053 SkASSERT(kTransfer_UploadType != uploadType && | 1237 SkASSERT(kTransfer_UploadType != uploadType && |
1054 (data || kNewTexture_UploadType != uploadType)); | 1238 (texels[0].fPixels || kNewTexture_UploadType != uploadType)); |
1055 | 1239 |
1056 // No support for software flip y, yet... | 1240 // No support for software flip y, yet... |
1057 SkASSERT(kBottomLeft_GrSurfaceOrigin != desc.fOrigin); | 1241 SkASSERT(kBottomLeft_GrSurfaceOrigin != desc.fOrigin); |
1058 | 1242 |
| 1243 const GrGLInterface* interface = this->glInterface(); |
| 1244 const GrGLCaps& caps = this->glCaps(); |
| 1245 |
1059 if (-1 == width) { | 1246 if (-1 == width) { |
1060 width = desc.fWidth; | 1247 width = desc.fWidth; |
1061 } | 1248 } |
1062 #ifdef SK_DEBUG | 1249 #ifdef SK_DEBUG |
1063 else { | 1250 else { |
1064 SkASSERT(width <= desc.fWidth); | 1251 SkASSERT(width <= desc.fWidth); |
1065 } | 1252 } |
1066 #endif | 1253 #endif |
1067 | 1254 |
1068 if (-1 == height) { | 1255 if (-1 == height) { |
1069 height = desc.fHeight; | 1256 height = desc.fHeight; |
1070 } | 1257 } |
1071 #ifdef SK_DEBUG | 1258 #ifdef SK_DEBUG |
1072 else { | 1259 else { |
1073 SkASSERT(height <= desc.fHeight); | 1260 SkASSERT(height <= desc.fHeight); |
1074 } | 1261 } |
1075 #endif | 1262 #endif |
1076 | 1263 |
1077 // Make sure that the width and height that we pass to OpenGL | |
1078 // is a multiple of the block size. | |
1079 size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, width, height); | |
1080 | |
1081 // We only need the internal format for compressed 2D textures. | 1264 // We only need the internal format for compressed 2D textures. |
1082 GrGLenum internalFormat; | 1265 GrGLenum internalFormat; |
1083 if (!this->glCaps().getCompressedTexImageFormats(desc.fConfig, &internalForm
at)) { | 1266 if (!caps.getCompressedTexImageFormats(desc.fConfig, &internalFormat)) { |
1084 return false; | 1267 return false; |
1085 } | 1268 } |
1086 | 1269 |
1087 if (kNewTexture_UploadType == uploadType) { | 1270 if (kNewTexture_UploadType == uploadType) { |
1088 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); | 1271 return allocate_and_populate_compressed_texture(desc, *interface, target
, internalFormat, |
1089 GL_ALLOC_CALL(this->glInterface(), | 1272 texels, width, height); |
1090 CompressedTexImage2D(target, | |
1091 0, // level | |
1092 internalFormat, | |
1093 width, height, | |
1094 0, // border | |
1095 SkToInt(dataSize), | |
1096 data)); | |
1097 GrGLenum error = check_alloc_error(desc, this->glInterface()); | |
1098 if (error != GR_GL_NO_ERROR) { | |
1099 return false; | |
1100 } | |
1101 } else { | 1273 } else { |
1102 // Paletted textures can't be updated. | 1274 // Paletted textures can't be updated. |
1103 if (GR_GL_PALETTE8_RGBA8 == internalFormat) { | 1275 if (GR_GL_PALETTE8_RGBA8 == internalFormat) { |
1104 return false; | 1276 return false; |
1105 } | 1277 } |
1106 GL_CALL(CompressedTexSubImage2D(target, | 1278 for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentM
ipLevel++) { |
1107 0, // level | 1279 if (texels[currentMipLevel].fPixels == nullptr) { |
1108 left, top, | 1280 continue; |
1109 width, height, | 1281 } |
1110 internalFormat, | 1282 |
1111 SkToInt(dataSize), | 1283 int twoToTheMipLevel = 1 << currentMipLevel; |
1112 data)); | 1284 int currentWidth = SkTMax(1, width / twoToTheMipLevel); |
| 1285 int currentHeight = SkTMax(1, height / twoToTheMipLevel); |
| 1286 |
| 1287 // Make sure that the width and height that we pass to OpenGL |
| 1288 // is a multiple of the block size. |
| 1289 size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, currentWi
dth, |
| 1290 currentHeight); |
| 1291 GL_CALL(CompressedTexSubImage2D(target, |
| 1292 currentMipLevel, |
| 1293 left, top, |
| 1294 currentWidth, |
| 1295 currentHeight, |
| 1296 internalFormat, |
| 1297 SkToInt(dataSize), |
| 1298 texels[currentMipLevel].fPixels)); |
| 1299 } |
1113 } | 1300 } |
1114 | 1301 |
1115 return true; | 1302 return true; |
1116 } | 1303 } |
1117 | 1304 |
1118 static bool renderbuffer_storage_msaa(const GrGLContext& ctx, | 1305 static bool renderbuffer_storage_msaa(const GrGLContext& ctx, |
1119 int sampleCount, | 1306 int sampleCount, |
1120 GrGLenum format, | 1307 GrGLenum format, |
1121 int width, int height) { | 1308 int width, int height) { |
1122 CLEAR_ERROR_BEFORE_ALLOC(ctx.interface()); | 1309 CLEAR_ERROR_BEFORE_ALLOC(ctx.interface()); |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1266 // SkDEBUGFAIL("null texture"); | 1453 // SkDEBUGFAIL("null texture"); |
1267 return nullptr; | 1454 return nullptr; |
1268 } | 1455 } |
1269 | 1456 |
1270 #if 0 && defined(SK_DEBUG) | 1457 #if 0 && defined(SK_DEBUG) |
1271 static size_t as_size_t(int x) { | 1458 static size_t as_size_t(int x) { |
1272 return x; | 1459 return x; |
1273 } | 1460 } |
1274 #endif | 1461 #endif |
1275 | 1462 |
| 1463 static GrGLTexture::IDDesc generate_gl_texture(const GrGLInterface* interface, |
| 1464 GrGpuResource::LifeCycle lifeCycl
e) { |
| 1465 GrGLTexture::IDDesc idDesc; |
| 1466 idDesc.fInfo.fID = 0; |
| 1467 GR_GL_CALL(interface, GenTextures(1, &idDesc.fInfo.fID)); |
| 1468 idDesc.fLifeCycle = lifeCycle; |
| 1469 // When we create the texture, we only |
| 1470 // create GL_TEXTURE_2D at the moment. |
| 1471 // External clients can do something different. |
| 1472 idDesc.fInfo.fTarget = GR_GL_TEXTURE_2D; |
| 1473 return idDesc; |
| 1474 } |
| 1475 |
| 1476 static void set_initial_texture_params(const GrGLInterface* interface, |
| 1477 const GrGLTextureInfo& info, |
| 1478 GrGLTexture::TexParams* initialTexParams)
{ |
| 1479 // Some drivers like to know filter/wrap before seeing glTexImage2D. Some |
| 1480 // drivers have a bug where an FBO won't be complete if it includes a |
| 1481 // texture that is not mipmap complete (considering the filter in use). |
| 1482 // we only set a subset here so invalidate first |
| 1483 initialTexParams->invalidate(); |
| 1484 initialTexParams->fMinFilter = GR_GL_NEAREST; |
| 1485 initialTexParams->fMagFilter = GR_GL_NEAREST; |
| 1486 initialTexParams->fWrapS = GR_GL_CLAMP_TO_EDGE; |
| 1487 initialTexParams->fWrapT = GR_GL_CLAMP_TO_EDGE; |
| 1488 GR_GL_CALL(interface, TexParameteri(info.fTarget, |
| 1489 GR_GL_TEXTURE_MAG_FILTER, |
| 1490 initialTexParams->fMagFilter)); |
| 1491 GR_GL_CALL(interface, TexParameteri(info.fTarget, |
| 1492 GR_GL_TEXTURE_MIN_FILTER, |
| 1493 initialTexParams->fMinFilter)); |
| 1494 GR_GL_CALL(interface, TexParameteri(info.fTarget, |
| 1495 GR_GL_TEXTURE_WRAP_S, |
| 1496 initialTexParams->fWrapS)); |
| 1497 GR_GL_CALL(interface, TexParameteri(info.fTarget, |
| 1498 GR_GL_TEXTURE_WRAP_T, |
| 1499 initialTexParams->fWrapT)); |
| 1500 } |
| 1501 |
1276 GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc, | 1502 GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc, |
1277 GrGpuResource::LifeCycle lifeCycle, | 1503 GrGpuResource::LifeCycle lifeCycle, |
1278 const void* srcData, size_t rowBytes) { | 1504 const SkTArray<GrMipLevel>& texels) { |
1279 // We fail if the MSAA was requested and is not available. | 1505 // We fail if the MSAA was requested and is not available. |
1280 if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleC
nt) { | 1506 if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleC
nt) { |
1281 //SkDebugf("MSAA RT requested but not supported on this platform."); | 1507 //SkDebugf("MSAA RT requested but not supported on this platform."); |
1282 return return_null_texture(); | 1508 return return_null_texture(); |
1283 } | 1509 } |
1284 | 1510 |
1285 bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag); | 1511 bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag); |
1286 | 1512 |
1287 GrGLTexture::IDDesc idDesc; | 1513 GrGLTexture::IDDesc idDesc; |
1288 idDesc.fLifeCycle = lifeCycle; | 1514 idDesc.fLifeCycle = lifeCycle; |
1289 GrGLTexture::TexParams initialTexParams; | 1515 GrGLTexture::TexParams initialTexParams; |
1290 if (!this->createTextureImpl(desc, &idDesc.fInfo, renderTarget, srcData, | 1516 if (!this->createTextureImpl(desc, &idDesc.fInfo, renderTarget, &initialTexP
arams, texels)) { |
1291 &initialTexParams, rowBytes)) { | |
1292 return return_null_texture(); | 1517 return return_null_texture(); |
1293 } | 1518 } |
1294 | 1519 |
1295 GrGLTexture* tex; | 1520 GrGLTexture* tex; |
1296 if (renderTarget) { | 1521 if (renderTarget) { |
1297 // unbind the texture from the texture unit before binding it to the fra
me buffer | 1522 // unbind the texture from the texture unit before binding it to the fra
me buffer |
1298 GL_CALL(BindTexture(idDesc.fInfo.fTarget, 0)); | 1523 GL_CALL(BindTexture(idDesc.fInfo.fTarget, 0)); |
1299 GrGLRenderTarget::IDDesc rtIDDesc; | 1524 GrGLRenderTarget::IDDesc rtIDDesc; |
1300 | 1525 |
1301 if (!this->createRenderTargetObjects(desc, lifeCycle, idDesc.fInfo, &rtI
DDesc)) { | 1526 if (!this->createRenderTargetObjects(desc, lifeCycle, idDesc.fInfo, &rtI
DDesc)) { |
1302 GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID)); | 1527 GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID)); |
1303 return return_null_texture(); | 1528 return return_null_texture(); |
1304 } | 1529 } |
1305 tex = new GrGLTextureRenderTarget(this, desc, idDesc, rtIDDesc); | 1530 tex = new GrGLTextureRenderTarget(this, desc, idDesc, rtIDDesc); |
1306 } else { | 1531 } else { |
1307 tex = new GrGLTexture(this, desc, idDesc); | 1532 bool wasMipMapDataProvided = false; |
| 1533 if (texels.count() > 1) { |
| 1534 wasMipMapDataProvided = true; |
| 1535 } |
| 1536 tex = new GrGLTexture(this, desc, idDesc, wasMipMapDataProvided); |
1308 } | 1537 } |
1309 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); | 1538 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); |
1310 #ifdef TRACE_TEXTURE_CREATION | 1539 #ifdef TRACE_TEXTURE_CREATION |
1311 SkDebugf("--- new texture [%d] size=(%d %d) config=%d\n", | 1540 SkDebugf("--- new texture [%d] size=(%d %d) config=%d\n", |
1312 glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig); | 1541 glTexDesc.fInfo.fID, desc.fWidth, desc.fHeight, desc.fConfig); |
1313 #endif | 1542 #endif |
1314 return tex; | 1543 return tex; |
1315 } | 1544 } |
1316 | 1545 |
1317 GrTexture* GrGLGpu::onCreateCompressedTexture(const GrSurfaceDesc& desc, | 1546 GrTexture* GrGLGpu::onCreateCompressedTexture(const GrSurfaceDesc& desc, |
1318 GrGpuResource::LifeCycle lifeCycle
, | 1547 GrGpuResource::LifeCycle lifeCycle
, |
1319 const void* srcData) { | 1548 const SkTArray<GrMipLevel>& texels
) { |
1320 // Make sure that we're not flipping Y. | 1549 // Make sure that we're not flipping Y. |
1321 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { | 1550 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { |
1322 return return_null_texture(); | 1551 return return_null_texture(); |
1323 } | 1552 } |
1324 | 1553 |
1325 GrGLTexture::IDDesc idDesc; | 1554 GrGLTexture::IDDesc idDesc = generate_gl_texture(this->glInterface(), lifeCy
cle); |
1326 idDesc.fInfo.fID = 0; | |
1327 GL_CALL(GenTextures(1, &idDesc.fInfo.fID)); | |
1328 idDesc.fLifeCycle = lifeCycle; | |
1329 // We only support GL_TEXTURE_2D at the moment. | |
1330 idDesc.fInfo.fTarget = GR_GL_TEXTURE_2D; | |
1331 | |
1332 if (!idDesc.fInfo.fID) { | 1555 if (!idDesc.fInfo.fID) { |
1333 return return_null_texture(); | 1556 return return_null_texture(); |
1334 } | 1557 } |
1335 | 1558 |
1336 this->setScratchTextureUnit(); | 1559 this->setScratchTextureUnit(); |
1337 GL_CALL(BindTexture(idDesc.fInfo.fTarget, idDesc.fInfo.fID)); | 1560 GL_CALL(BindTexture(idDesc.fInfo.fTarget, idDesc.fInfo.fID)); |
1338 | 1561 |
1339 // Some drivers like to know filter/wrap before seeing glTexImage2D. Some | |
1340 // drivers have a bug where an FBO won't be complete if it includes a | |
1341 // texture that is not mipmap complete (considering the filter in use). | |
1342 GrGLTexture::TexParams initialTexParams; | 1562 GrGLTexture::TexParams initialTexParams; |
1343 // we only set a subset here so invalidate first | 1563 set_initial_texture_params(this->glInterface(), idDesc.fInfo, &initialTexPar
ams); |
1344 initialTexParams.invalidate(); | |
1345 initialTexParams.fMinFilter = GR_GL_NEAREST; | |
1346 initialTexParams.fMagFilter = GR_GL_NEAREST; | |
1347 initialTexParams.fWrapS = GR_GL_CLAMP_TO_EDGE; | |
1348 initialTexParams.fWrapT = GR_GL_CLAMP_TO_EDGE; | |
1349 GL_CALL(TexParameteri(idDesc.fInfo.fTarget, | |
1350 GR_GL_TEXTURE_MAG_FILTER, | |
1351 initialTexParams.fMagFilter)); | |
1352 GL_CALL(TexParameteri(idDesc.fInfo.fTarget, | |
1353 GR_GL_TEXTURE_MIN_FILTER, | |
1354 initialTexParams.fMinFilter)); | |
1355 GL_CALL(TexParameteri(idDesc.fInfo.fTarget, | |
1356 GR_GL_TEXTURE_WRAP_S, | |
1357 initialTexParams.fWrapS)); | |
1358 GL_CALL(TexParameteri(idDesc.fInfo.fTarget, | |
1359 GR_GL_TEXTURE_WRAP_T, | |
1360 initialTexParams.fWrapT)); | |
1361 | 1564 |
1362 if (!this->uploadCompressedTexData(desc, idDesc.fInfo.fTarget, srcData)) { | 1565 if (!this->uploadCompressedTexData(desc, idDesc.fInfo.fTarget, texels)) { |
1363 GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID)); | 1566 GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID)); |
1364 return return_null_texture(); | 1567 return return_null_texture(); |
1365 } | 1568 } |
1366 | 1569 |
1367 GrGLTexture* tex; | 1570 GrGLTexture* tex; |
1368 tex = new GrGLTexture(this, desc, idDesc); | 1571 tex = new GrGLTexture(this, desc, idDesc); |
1369 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); | 1572 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); |
1370 #ifdef TRACE_TEXTURE_CREATION | 1573 #ifdef TRACE_TEXTURE_CREATION |
1371 SkDebugf("--- new compressed texture [%d] size=(%d %d) config=%d\n", | 1574 SkDebugf("--- new compressed texture [%d] size=(%d %d) config=%d\n", |
1372 glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig); | 1575 glTexDesc.fInfo.fID, desc.fWidth, desc.fHeight, desc.fConfig); |
1373 #endif | 1576 #endif |
1374 return tex; | 1577 return tex; |
1375 } | 1578 } |
1376 | 1579 |
1377 namespace { | 1580 namespace { |
1378 | 1581 |
1379 const GrGLuint kUnknownBitCount = GrGLStencilAttachment::kUnknownBitCount; | 1582 const GrGLuint kUnknownBitCount = GrGLStencilAttachment::kUnknownBitCount; |
1380 | 1583 |
1381 void inline get_stencil_rb_sizes(const GrGLInterface* gl, | 1584 void inline get_stencil_rb_sizes(const GrGLInterface* gl, |
1382 GrGLStencilAttachment::Format* format) { | 1585 GrGLStencilAttachment::Format* format) { |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1505 } | 1708 } |
1506 GL_CALL(DeleteTextures(1, &colorID)); | 1709 GL_CALL(DeleteTextures(1, &colorID)); |
1507 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, 0)); | 1710 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, 0)); |
1508 GL_CALL(DeleteFramebuffers(1, &fb)); | 1711 GL_CALL(DeleteFramebuffers(1, &fb)); |
1509 fGLContext->caps()->setStencilFormatIndexForConfig(config, firstWorkingS
tencilFormatIndex); | 1712 fGLContext->caps()->setStencilFormatIndexForConfig(config, firstWorkingS
tencilFormatIndex); |
1510 } | 1713 } |
1511 return this->glCaps().getStencilFormatIndexForConfig(config); | 1714 return this->glCaps().getStencilFormatIndexForConfig(config); |
1512 } | 1715 } |
1513 | 1716 |
1514 bool GrGLGpu::createTextureImpl(const GrSurfaceDesc& desc, GrGLTextureInfo* info
, | 1717 bool GrGLGpu::createTextureImpl(const GrSurfaceDesc& desc, GrGLTextureInfo* info
, |
1515 bool renderTarget, const void* srcData, | 1718 bool renderTarget, GrGLTexture::TexParams* initi
alTexParams, |
1516 GrGLTexture::TexParams* initialTexParams, size_t
rowBytes) { | 1719 const SkTArray<GrMipLevel>& texels) { |
1517 // Some drivers like to know filter/wrap before seeing glTexImage2D. Some | |
1518 // drivers have a bug where an FBO won't be complete if it includes a | |
1519 // texture that is not mipmap complete (considering the filter in use). | |
1520 | |
1521 // we only set a subset here so invalidate first | |
1522 initialTexParams->invalidate(); | |
1523 initialTexParams->fMinFilter = GR_GL_NEAREST; | |
1524 initialTexParams->fMagFilter = GR_GL_NEAREST; | |
1525 initialTexParams->fWrapS = GR_GL_CLAMP_TO_EDGE; | |
1526 initialTexParams->fWrapT = GR_GL_CLAMP_TO_EDGE; | |
1527 | |
1528 if (desc.fTextureStorageAllocator.fAllocateTextureStorage) { | 1720 if (desc.fTextureStorageAllocator.fAllocateTextureStorage) { |
1529 return this->createTextureExternalAllocatorImpl(desc, info, srcData, row
Bytes); | 1721 return this->createTextureExternalAllocatorImpl(desc, info, texels); |
1530 } | 1722 } |
1531 | 1723 |
1532 info->fID = 0; | 1724 info->fID = 0; |
1533 info->fTarget = GR_GL_TEXTURE_2D; | 1725 info->fTarget = GR_GL_TEXTURE_2D; |
1534 GL_CALL(GenTextures(1, &(info->fID))); | 1726 GL_CALL(GenTextures(1, &(info->fID))); |
1535 | 1727 |
1536 if (!info->fID) { | 1728 if (!info->fID) { |
1537 return false; | 1729 return false; |
1538 } | 1730 } |
1539 | 1731 |
1540 this->setScratchTextureUnit(); | 1732 this->setScratchTextureUnit(); |
1541 GL_CALL(BindTexture(info->fTarget, info->fID)); | 1733 GL_CALL(BindTexture(info->fTarget, info->fID)); |
1542 | 1734 |
1543 if (renderTarget && this->glCaps().textureUsageSupport()) { | 1735 if (renderTarget && this->glCaps().textureUsageSupport()) { |
1544 // provides a hint about how this texture will be used | 1736 // provides a hint about how this texture will be used |
1545 GL_CALL(TexParameteri(info->fTarget, | 1737 GL_CALL(TexParameteri(info->fTarget, |
1546 GR_GL_TEXTURE_USAGE, | 1738 GR_GL_TEXTURE_USAGE, |
1547 GR_GL_FRAMEBUFFER_ATTACHMENT)); | 1739 GR_GL_FRAMEBUFFER_ATTACHMENT)); |
1548 } | 1740 } |
1549 | 1741 |
1550 GL_CALL(TexParameteri(info->fTarget, | 1742 if (info) { |
1551 GR_GL_TEXTURE_MAG_FILTER, | 1743 set_initial_texture_params(this->glInterface(), *info, initialTexParams)
; |
1552 initialTexParams->fMagFilter)); | 1744 } |
1553 GL_CALL(TexParameteri(info->fTarget, | |
1554 GR_GL_TEXTURE_MIN_FILTER, | |
1555 initialTexParams->fMinFilter)); | |
1556 GL_CALL(TexParameteri(info->fTarget, | |
1557 GR_GL_TEXTURE_WRAP_S, | |
1558 initialTexParams->fWrapS)); | |
1559 GL_CALL(TexParameteri(info->fTarget, | |
1560 GR_GL_TEXTURE_WRAP_T, | |
1561 initialTexParams->fWrapT)); | |
1562 if (!this->uploadTexData(desc, info->fTarget, kNewTexture_UploadType, 0, 0, | 1745 if (!this->uploadTexData(desc, info->fTarget, kNewTexture_UploadType, 0, 0, |
1563 desc.fWidth, desc.fHeight, | 1746 desc.fWidth, desc.fHeight, |
1564 desc.fConfig, srcData, rowBytes)) { | 1747 desc.fConfig, texels)) { |
1565 GL_CALL(DeleteTextures(1, &(info->fID))); | 1748 GL_CALL(DeleteTextures(1, &(info->fID))); |
1566 return false; | 1749 return false; |
1567 } | 1750 } |
1568 return true; | 1751 return true; |
1569 } | 1752 } |
1570 | 1753 |
1571 bool GrGLGpu::createTextureExternalAllocatorImpl( | 1754 bool GrGLGpu::createTextureExternalAllocatorImpl(const GrSurfaceDesc& desc, |
1572 const GrSurfaceDesc& desc, GrGLTextureInfo* info, const void* srcData, s
ize_t rowBytes) { | 1755 GrGLTextureInfo* info, |
| 1756 const SkTArray<GrMipLevel>& tex
els) { |
| 1757 // We do not make SkTArray available outside of Skia, |
| 1758 // and so we do not want to allow mipmaps to external |
| 1759 // allocators just yet. |
| 1760 SkASSERT(texels.count() == 1); |
| 1761 SkSTArray<1, GrMipLevel> texelsShallowCopy(1); |
| 1762 texelsShallowCopy.push_back(texels[0]); |
| 1763 |
1573 switch (desc.fTextureStorageAllocator.fAllocateTextureStorage( | 1764 switch (desc.fTextureStorageAllocator.fAllocateTextureStorage( |
1574 desc.fTextureStorageAllocator.fCtx, reinterpret_cast<GrBacke
ndObject>(info), | 1765 desc.fTextureStorageAllocator.fCtx, reinterpret_cast<GrBacke
ndObject>(info), |
1575 desc.fWidth, desc.fHeight, desc.fConfig, srcData, desc.fOrig
in)) { | 1766 desc.fWidth, desc.fHeight, desc.fConfig, texelsShallowCopy[0
].fPixels, |
| 1767 desc.fOrigin)) { |
1576 case GrTextureStorageAllocator::Result::kSucceededAndUploaded: | 1768 case GrTextureStorageAllocator::Result::kSucceededAndUploaded: |
1577 return true; | 1769 return true; |
1578 case GrTextureStorageAllocator::Result::kFailed: | 1770 case GrTextureStorageAllocator::Result::kFailed: |
1579 return false; | 1771 return false; |
1580 case GrTextureStorageAllocator::Result::kSucceededWithoutUpload: | 1772 case GrTextureStorageAllocator::Result::kSucceededWithoutUpload: |
1581 break; | 1773 break; |
1582 } | 1774 } |
1583 | 1775 |
1584 if (!this->uploadTexData(desc, info->fTarget, kNewTexture_UploadType, 0, 0, | 1776 if (!this->uploadTexData(desc, info->fTarget, kNewTexture_UploadType, 0, 0, |
1585 desc.fWidth, desc.fHeight, | 1777 desc.fWidth, desc.fHeight, |
1586 desc.fConfig, srcData, rowBytes)) { | 1778 desc.fConfig, texelsShallowCopy)) { |
1587 desc.fTextureStorageAllocator.fDeallocateTextureStorage( | 1779 desc.fTextureStorageAllocator.fDeallocateTextureStorage( |
1588 desc.fTextureStorageAllocator.fCtx, reinterpret_cast<GrBackendOb
ject>(info)); | 1780 desc.fTextureStorageAllocator.fCtx, reinterpret_cast<GrBackendOb
ject>(info)); |
1589 return false; | 1781 return false; |
1590 } | 1782 } |
1591 return true; | 1783 return true; |
1592 } | 1784 } |
1593 | 1785 |
1594 GrStencilAttachment* GrGLGpu::createStencilAttachmentForRenderTarget(const GrRen
derTarget* rt, | 1786 GrStencilAttachment* GrGLGpu::createStencilAttachmentForRenderTarget(const GrRen
derTarget* rt, |
1595 int width, | 1787 int width, |
1596 int height)
{ | 1788 int height)
{ |
(...skipping 1435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3032 | 3224 |
3033 if (GrTextureParams::kMipMap_FilterMode == filterMode) { | 3225 if (GrTextureParams::kMipMap_FilterMode == filterMode) { |
3034 if (!this->caps()->mipMapSupport() || GrPixelConfigIsCompressed(texture-
>config())) { | 3226 if (!this->caps()->mipMapSupport() || GrPixelConfigIsCompressed(texture-
>config())) { |
3035 filterMode = GrTextureParams::kBilerp_FilterMode; | 3227 filterMode = GrTextureParams::kBilerp_FilterMode; |
3036 } | 3228 } |
3037 } | 3229 } |
3038 | 3230 |
3039 newTexParams.fMinFilter = glMinFilterModes[filterMode]; | 3231 newTexParams.fMinFilter = glMinFilterModes[filterMode]; |
3040 newTexParams.fMagFilter = glMagFilterModes[filterMode]; | 3232 newTexParams.fMagFilter = glMagFilterModes[filterMode]; |
3041 | 3233 |
3042 if (GrTextureParams::kMipMap_FilterMode == filterMode && | 3234 if (GrTextureParams::kMipMap_FilterMode == filterMode) { |
3043 texture->texturePriv().mipMapsAreDirty()) { | 3235 if (texture->texturePriv().mipMapsAreDirty()) { |
3044 GL_CALL(GenerateMipmap(target)); | 3236 GL_CALL(GenerateMipmap(target)); |
3045 texture->texturePriv().dirtyMipMaps(false); | 3237 texture->texturePriv().dirtyMipMaps(false); |
| 3238 texture->texturePriv().setMaxMipMapLevel(SkMipMap::ComputeLevelCount
( |
| 3239 texture->width(), texture->height())); |
| 3240 } |
3046 } | 3241 } |
3047 | 3242 |
| 3243 newTexParams.fMaxMipMapLevel = texture->texturePriv().maxMipMapLevel(); |
| 3244 |
3048 newTexParams.fWrapS = tile_to_gl_wrap(params.getTileModeX()); | 3245 newTexParams.fWrapS = tile_to_gl_wrap(params.getTileModeX()); |
3049 newTexParams.fWrapT = tile_to_gl_wrap(params.getTileModeY()); | 3246 newTexParams.fWrapT = tile_to_gl_wrap(params.getTileModeY()); |
3050 get_tex_param_swizzle(texture->config(), this->glCaps(), newTexParams.fSwizz
leRGBA); | 3247 get_tex_param_swizzle(texture->config(), this->glCaps(), newTexParams.fSwizz
leRGBA); |
3051 if (setAll || newTexParams.fMagFilter != oldTexParams.fMagFilter) { | 3248 if (setAll || newTexParams.fMagFilter != oldTexParams.fMagFilter) { |
3052 this->setTextureUnit(unitIdx); | 3249 this->setTextureUnit(unitIdx); |
3053 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAG_FILTER, newTexParams.fMa
gFilter)); | 3250 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAG_FILTER, newTexParams.fMa
gFilter)); |
3054 } | 3251 } |
3055 if (setAll || newTexParams.fMinFilter != oldTexParams.fMinFilter) { | 3252 if (setAll || newTexParams.fMinFilter != oldTexParams.fMinFilter) { |
3056 this->setTextureUnit(unitIdx); | 3253 this->setTextureUnit(unitIdx); |
3057 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_FILTER, newTexParams.fMi
nFilter)); | 3254 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_FILTER, newTexParams.fMi
nFilter)); |
3058 } | 3255 } |
| 3256 if (setAll || newTexParams.fMaxMipMapLevel != oldTexParams.fMaxMipMapLevel)
{ |
| 3257 if (newTexParams.fMaxMipMapLevel != 0) { |
| 3258 this->setTextureUnit(unitIdx); |
| 3259 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_LOD, 0)); |
| 3260 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_BASE_LEVEL, 0)); |
| 3261 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAX_LOD, |
| 3262 newTexParams.fMaxMipMapLevel)); |
| 3263 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAX_LEVEL, |
| 3264 newTexParams.fMaxMipMapLevel)); |
| 3265 } |
| 3266 } |
3059 if (setAll || newTexParams.fWrapS != oldTexParams.fWrapS) { | 3267 if (setAll || newTexParams.fWrapS != oldTexParams.fWrapS) { |
3060 this->setTextureUnit(unitIdx); | 3268 this->setTextureUnit(unitIdx); |
3061 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_S, newTexParams.fWrapS)
); | 3269 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_S, newTexParams.fWrapS)
); |
3062 } | 3270 } |
3063 if (setAll || newTexParams.fWrapT != oldTexParams.fWrapT) { | 3271 if (setAll || newTexParams.fWrapT != oldTexParams.fWrapT) { |
3064 this->setTextureUnit(unitIdx); | 3272 this->setTextureUnit(unitIdx); |
3065 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_T, newTexParams.fWrapT)
); | 3273 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_WRAP_T, newTexParams.fWrapT)
); |
3066 } | 3274 } |
3067 if (this->glCaps().textureSwizzleSupport() && | 3275 if (this->glCaps().textureSwizzleSupport() && |
3068 (setAll || memcmp(newTexParams.fSwizzleRGBA, | 3276 (setAll || memcmp(newTexParams.fSwizzleRGBA, |
(...skipping 940 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4009 if (GR_GL_TEXTURE_EXTERNAL == glTexture->target() || | 4217 if (GR_GL_TEXTURE_EXTERNAL == glTexture->target() || |
4010 GR_GL_TEXTURE_RECTANGLE == glTexture->target()) { | 4218 GR_GL_TEXTURE_RECTANGLE == glTexture->target()) { |
4011 copyParams->fFilter = GrTextureParams::kNone_FilterMode; | 4219 copyParams->fFilter = GrTextureParams::kNone_FilterMode; |
4012 copyParams->fWidth = texture->width(); | 4220 copyParams->fWidth = texture->width(); |
4013 copyParams->fHeight = texture->height(); | 4221 copyParams->fHeight = texture->height(); |
4014 return true; | 4222 return true; |
4015 } | 4223 } |
4016 } | 4224 } |
4017 return false; | 4225 return false; |
4018 } | 4226 } |
OLD | NEW |