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