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

Side by Side Diff: src/gpu/gl/GrGLGpu.cpp

Issue 1249543003: Creating functions for uploading a mipmapped texture. (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: Rebasing. Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/gl/GrGLGpu.h ('k') | src/gpu/gl/GrGLTexture.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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 &currentWidth,
1077 &currentHeight,
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « src/gpu/gl/GrGLGpu.h ('k') | src/gpu/gl/GrGLTexture.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698