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

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