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 | 8 |
9 #include "GrGLGpu.h" | 9 #include "GrGLGpu.h" |
10 #include "GrGLGLSL.h" | 10 #include "GrGLGLSL.h" |
11 #include "GrGLStencilAttachment.h" | 11 #include "GrGLStencilAttachment.h" |
12 #include "GrGLTextureRenderTarget.h" | 12 #include "GrGLTextureRenderTarget.h" |
13 #include "GrGpuResourcePriv.h" | 13 #include "GrGpuResourcePriv.h" |
14 #include "GrPipeline.h" | 14 #include "GrPipeline.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 "SkMipMapLevel.h" | |
23 #include "SkStrokeRec.h" | 24 #include "SkStrokeRec.h" |
24 #include "SkTemplates.h" | 25 #include "SkTemplates.h" |
26 #include "SkTypes.h" | |
25 | 27 |
26 #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X) | 28 #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X) |
27 #define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->glInterface(), RET, X) | 29 #define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->glInterface(), RET, X) |
28 | 30 |
29 #define SKIP_CACHE_CHECK true | 31 #define SKIP_CACHE_CHECK true |
30 | 32 |
31 #if GR_GL_CHECK_ALLOC_WITH_GET_ERROR | 33 #if GR_GL_CHECK_ALLOC_WITH_GET_ERROR |
32 #define CLEAR_ERROR_BEFORE_ALLOC(iface) GrGLClearErr(iface) | 34 #define CLEAR_ERROR_BEFORE_ALLOC(iface) GrGLClearErr(iface) |
33 #define GL_ALLOC_CALL(iface, call) GR_GL_CALL_NOERRCHECK(iface, call) | 35 #define GL_ALLOC_CALL(iface, call) GR_GL_CALL_NOERRCHECK(iface, call) |
34 #define CHECK_ALLOC_ERROR(iface) GR_GL_GET_ERROR(iface) | 36 #define CHECK_ALLOC_ERROR(iface) GR_GL_GET_ERROR(iface) |
35 #else | 37 #else |
36 #define CLEAR_ERROR_BEFORE_ALLOC(iface) | 38 #define CLEAR_ERROR_BEFORE_ALLOC(iface) |
37 #define GL_ALLOC_CALL(iface, call) GR_GL_CALL(iface, call) | 39 #define GL_ALLOC_CALL(iface, call) GR_GL_CALL(iface, call) |
38 #define CHECK_ALLOC_ERROR(iface) GR_GL_NO_ERROR | 40 #define CHECK_ALLOC_ERROR(iface) GR_GL_NO_ERROR |
39 #endif | 41 #endif |
40 | 42 |
43 #if defined(GOOGLE3) | |
44 // Stack frame size is limited in GOOGLE3. | |
45 typedef SkAutoSMalloc<64 * 128> SkAutoSMallocTexels; | |
46 #else | |
47 typedef SkAutoSMalloc<128 * 128> SkAutoSMallocTexels; | |
48 #endif | |
41 | 49 |
42 /////////////////////////////////////////////////////////////////////////////// | 50 /////////////////////////////////////////////////////////////////////////////// |
43 | 51 |
44 | 52 |
45 static const GrGLenum gXfermodeEquation2Blend[] = { | 53 static const GrGLenum gXfermodeEquation2Blend[] = { |
46 // Basic OpenGL blend equations. | 54 // Basic OpenGL blend equations. |
47 GR_GL_FUNC_ADD, | 55 GR_GL_FUNC_ADD, |
48 GR_GL_FUNC_SUBTRACT, | 56 GR_GL_FUNC_SUBTRACT, |
49 GR_GL_FUNC_REVERSE_SUBTRACT, | 57 GR_GL_FUNC_REVERSE_SUBTRACT, |
50 | 58 |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
518 idDesc.fRTFBOID = static_cast<GrGLuint>(wrapDesc.fRenderTargetHandle); | 526 idDesc.fRTFBOID = static_cast<GrGLuint>(wrapDesc.fRenderTargetHandle); |
519 idDesc.fMSColorRenderbufferID = 0; | 527 idDesc.fMSColorRenderbufferID = 0; |
520 idDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID; | 528 idDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID; |
521 switch (ownership) { | 529 switch (ownership) { |
522 case kAdopt_GrWrapOwnership: | 530 case kAdopt_GrWrapOwnership: |
523 idDesc.fLifeCycle = GrGpuResource::kAdopted_LifeCycle; | 531 idDesc.fLifeCycle = GrGpuResource::kAdopted_LifeCycle; |
524 break; | 532 break; |
525 case kBorrow_GrWrapOwnership: | 533 case kBorrow_GrWrapOwnership: |
526 idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle; | 534 idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle; |
527 break; | 535 break; |
528 } | 536 } |
529 idDesc.fSampleConfig = GrRenderTarget::kUnified_SampleConfig; | 537 idDesc.fSampleConfig = GrRenderTarget::kUnified_SampleConfig; |
530 | 538 |
531 GrSurfaceDesc desc; | 539 GrSurfaceDesc desc; |
532 desc.fConfig = wrapDesc.fConfig; | 540 desc.fConfig = wrapDesc.fConfig; |
533 desc.fFlags = kCheckAllocation_GrSurfaceFlag | kRenderTarget_GrSurfaceFlag; | 541 desc.fFlags = kCheckAllocation_GrSurfaceFlag | kRenderTarget_GrSurfaceFlag; |
534 desc.fWidth = wrapDesc.fWidth; | 542 desc.fWidth = wrapDesc.fWidth; |
535 desc.fHeight = wrapDesc.fHeight; | 543 desc.fHeight = wrapDesc.fHeight; |
536 desc.fSampleCnt = SkTMin(wrapDesc.fSampleCnt, this->caps()->maxSampleCount() ); | 544 desc.fSampleCnt = SkTMin(wrapDesc.fSampleCnt, this->caps()->maxSampleCount() ); |
537 desc.fOrigin = resolve_origin(wrapDesc.fOrigin, true); | 545 desc.fOrigin = resolve_origin(wrapDesc.fOrigin, true); |
538 | 546 |
539 return GrGLRenderTarget::CreateWrapped(this, desc, idDesc, wrapDesc.fStencil Bits); | 547 return GrGLRenderTarget::CreateWrapped(this, desc, idDesc, wrapDesc.fStencil Bits); |
540 } | 548 } |
541 | 549 |
542 //////////////////////////////////////////////////////////////////////////////// | 550 //////////////////////////////////////////////////////////////////////////////// |
543 bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height, | 551 bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height, |
544 size_t rowBytes, GrPixelConfig srcConfig, | 552 GrPixelConfig srcConfig, |
545 DrawPreference* drawPreference, | 553 DrawPreference* drawPreference, |
546 WritePixelTempDrawInfo* tempDrawInfo) { | 554 WritePixelTempDrawInfo* tempDrawInfo) { |
547 if (kIndex_8_GrPixelConfig == srcConfig || GrPixelConfigIsCompressed(dstSurf ace->config())) { | 555 if (kIndex_8_GrPixelConfig == srcConfig || GrPixelConfigIsCompressed(dstSurf ace->config())) { |
548 return false; | 556 return false; |
549 } | 557 } |
550 | 558 |
551 // This subclass only allows writes to textures. If the dst is not a texture we have to draw | 559 // This subclass only allows writes to textures. If the dst is not a texture we have to draw |
552 // into it. We could use glDrawPixels on GLs that have it, but we don't toda y. | 560 // into it. We could use glDrawPixels on GLs that have it, but we don't toda y. |
553 if (!dstSurface->asTexture()) { | 561 if (!dstSurface->asTexture()) { |
554 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); | 562 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
619 // Write or transfer of pixels is not implemented for TEXTURE_EXTERNAL textu res | 627 // Write or transfer of pixels is not implemented for TEXTURE_EXTERNAL textu res |
620 if (GR_GL_TEXTURE_EXTERNAL == glTex->target()) { | 628 if (GR_GL_TEXTURE_EXTERNAL == glTex->target()) { |
621 return false; | 629 return false; |
622 } | 630 } |
623 | 631 |
624 return true; | 632 return true; |
625 } | 633 } |
626 | 634 |
627 bool GrGLGpu::onWritePixels(GrSurface* surface, | 635 bool GrGLGpu::onWritePixels(GrSurface* surface, |
628 int left, int top, int width, int height, | 636 int left, int top, int width, int height, |
629 GrPixelConfig config, const void* buffer, | 637 GrPixelConfig config, |
630 size_t rowBytes) { | 638 const SkTArray<SkMipMapLevel>& texels) { |
631 GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture()); | 639 GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture()); |
632 | 640 |
633 if (!check_write_and_transfer_input(glTex, surface, config)) { | 641 if (!check_write_and_transfer_input(glTex, surface, config)) { |
634 return false; | 642 return false; |
635 } | 643 } |
636 | 644 |
637 this->setScratchTextureUnit(); | 645 this->setScratchTextureUnit(); |
638 GL_CALL(BindTexture(glTex->target(), glTex->textureID())); | 646 GL_CALL(BindTexture(glTex->target(), glTex->textureID())); |
639 | 647 |
640 bool success = false; | 648 bool success = false; |
641 if (GrPixelConfigIsCompressed(glTex->desc().fConfig)) { | 649 if (GrPixelConfigIsCompressed(glTex->desc().fConfig)) { |
642 // We check that config == desc.fConfig in GrGLGpu::canWriteTexturePixel s() | 650 // We check that config == desc.fConfig in GrGLGpu::canWriteTexturePixel s() |
643 SkASSERT(config == glTex->desc().fConfig); | 651 SkASSERT(config == glTex->desc().fConfig); |
644 success = this->uploadCompressedTexData(glTex->desc(), glTex->target(), buffer, | 652 success = this->uploadCompressedTexData(glTex->desc(), glTex->target(), texels, |
645 kWrite_UploadType, left, top, wi dth, height); | 653 kWrite_UploadType, left, top, wi dth, height); |
646 } else { | 654 } else { |
647 success = this->uploadTexData(glTex->desc(), glTex->target(), kWrite_Upl oadType, | 655 success = this->uploadTexData(glTex->desc(), glTex->target(), kWrite_Upl oadType, |
648 left, top, width, height, config, buffer, rowBytes); | 656 left, top, width, height, config, texels); |
649 } | 657 } |
650 | 658 |
651 if (success) { | 659 return success; |
652 glTex->texturePriv().dirtyMipMaps(true); | |
653 return true; | |
654 } | |
655 | |
656 return false; | |
657 } | 660 } |
658 | 661 |
659 bool GrGLGpu::onTransferPixels(GrSurface* surface, | 662 bool GrGLGpu::onTransferPixels(GrSurface* surface, |
660 int left, int top, int width, int height, | 663 int left, int top, int width, int height, |
661 GrPixelConfig config, GrTransferBuffer* buffer, | 664 GrPixelConfig config, GrTransferBuffer* buffer, |
662 size_t offset, size_t rowBytes) { | 665 size_t offset, size_t rowBytes) { |
663 GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture()); | 666 GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture()); |
664 | 667 |
665 if (!check_write_and_transfer_input(glTex, surface, config)) { | 668 if (!check_write_and_transfer_input(glTex, surface, config)) { |
666 return false; | 669 return false; |
667 } | 670 } |
668 | 671 |
669 // For the moment, can't transfer compressed data | 672 // For the moment, can't transfer compressed data |
670 if (GrPixelConfigIsCompressed(glTex->desc().fConfig)) { | 673 if (GrPixelConfigIsCompressed(glTex->desc().fConfig)) { |
671 return false; | 674 return false; |
672 } | 675 } |
673 | 676 |
674 this->setScratchTextureUnit(); | 677 this->setScratchTextureUnit(); |
675 GL_CALL(BindTexture(glTex->target(), glTex->textureID())); | 678 GL_CALL(BindTexture(glTex->target(), glTex->textureID())); |
676 | 679 |
677 SkASSERT(!buffer->isMapped()); | 680 SkASSERT(!buffer->isMapped()); |
678 GrGLTransferBuffer* glBuffer = reinterpret_cast<GrGLTransferBuffer*>(buffer) ; | 681 GrGLTransferBuffer* glBuffer = reinterpret_cast<GrGLTransferBuffer*>(buffer) ; |
679 // bind the transfer buffer | 682 // bind the transfer buffer |
680 SkASSERT(GR_GL_PIXEL_UNPACK_BUFFER == glBuffer->bufferType() || | 683 SkASSERT(GR_GL_PIXEL_UNPACK_BUFFER == glBuffer->bufferType() || |
681 GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM == glBuffer->bufferType ()); | 684 GR_GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM == glBuffer->bufferType ()); |
682 GL_CALL(BindBuffer(glBuffer->bufferType(), glBuffer->bufferID())); | 685 GL_CALL(BindBuffer(glBuffer->bufferType(), glBuffer->bufferID())); |
683 | 686 |
684 bool success = false; | 687 bool success = false; |
688 SkMipMapLevel mipLevel(buffer, rowBytes, width, height); | |
689 SkSTArray<1, SkMipMapLevel> texels; | |
690 texels.push_back(mipLevel); | |
685 success = this->uploadTexData(glTex->desc(), glTex->target(), kTransfer_Uplo adType, | 691 success = this->uploadTexData(glTex->desc(), glTex->target(), kTransfer_Uplo adType, |
686 left, top, width, height, config, buffer, rowB ytes); | 692 left, top, width, height, config, texels); |
687 | 693 |
688 if (success) { | 694 if (success) { |
689 glTex->texturePriv().dirtyMipMaps(true); | 695 glTex->texturePriv().dirtyMipMaps(true); |
690 return true; | 696 return true; |
691 } | 697 } |
692 | 698 |
693 return false; | 699 return false; |
694 } | 700 } |
695 | 701 |
696 // For GL_[UN]PACK_ALIGNMENT. | 702 // For GL_[UN]PACK_ALIGNMENT. |
(...skipping 19 matching lines...) Expand all Loading... | |
716 | 722 |
717 static inline GrGLenum check_alloc_error(const GrSurfaceDesc& desc, | 723 static inline GrGLenum check_alloc_error(const GrSurfaceDesc& desc, |
718 const GrGLInterface* interface) { | 724 const GrGLInterface* interface) { |
719 if (SkToBool(desc.fFlags & kCheckAllocation_GrSurfaceFlag)) { | 725 if (SkToBool(desc.fFlags & kCheckAllocation_GrSurfaceFlag)) { |
720 return GR_GL_GET_ERROR(interface); | 726 return GR_GL_GET_ERROR(interface); |
721 } else { | 727 } else { |
722 return CHECK_ALLOC_ERROR(interface); | 728 return CHECK_ALLOC_ERROR(interface); |
723 } | 729 } |
724 } | 730 } |
725 | 731 |
732 /** | |
733 * Creates storage space for the texture and fills it with texels. | |
734 * | |
735 * @param desc The surface descriptor for the texture being created. | |
736 * @param interface The GL interface in use. | |
737 * @param useTexStorage The result of a call to can_use_tex_storage(). | |
738 * @param internalFormat The data format used for the internal storage of the te xture. | |
739 * @param externalFormat The data format used for the external storage of the te xture. | |
740 * @param externalType The type of the data used for the external storage of t he texture. | |
741 * @param texels The texel data of the texture being created. | |
742 * @param succeeded Set to true if allocating and populating the texture co mpleted | |
743 * without error. | |
744 */ | |
745 static void allocate_and_populate_uncompressed_texture(const GrSurfaceDesc& desc , | |
746 const GrGLInterface& inte rface, | |
747 GrGLenum target, | |
748 GrGLenum internalFormat, | |
749 GrGLenum externalFormat, | |
750 GrGLenum externalType, | |
751 const SkTArray<SkMipMapLe vel>& texels, | |
752 bool* succeeded) { | |
753 CLEAR_ERROR_BEFORE_ALLOC(&interface); | |
754 *succeeded = true; | |
755 for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLe vel++) { | |
756 const void* currentMipData = texels[currentMipLevel].fTexelsOrOffset; | |
757 // Even if curremtMipData is nullptr, continue to call TexImage2D. | |
758 // This will allocate texture memory which we can later populate. | |
759 GL_ALLOC_CALL(&interface, | |
760 TexImage2D(target, | |
761 currentMipLevel, | |
762 internalFormat, | |
763 texels[currentMipLevel].fWidth, | |
764 texels[currentMipLevel].fHeight, | |
765 0, // border | |
766 externalFormat, externalType, | |
767 currentMipData)); | |
768 GrGLenum error = check_alloc_error(desc, &interface); | |
769 if (error != GR_GL_NO_ERROR) { | |
770 *succeeded = false; | |
771 break; | |
772 } | |
773 } | |
774 } | |
775 | |
776 /** | |
777 * Creates storage space for the texture and fills it with texels. | |
778 * | |
779 * @param desc The surface descriptor for the texture being created. | |
780 * @param interface The GL interface in use. | |
781 * @param useTexStorage The result of a call to can_use_tex_storage(). | |
782 * @param internalFormat The data format used for the internal storage of the te xture. | |
783 * @param texels The texel data of the texture being created. | |
784 */ | |
785 static bool allocate_and_populate_compressed_texture(const GrSurfaceDesc& desc, | |
786 const GrGLInterface& interf ace, | |
787 GrGLenum target, GrGLenum i nternalFormat, | |
788 const SkTArray<SkMipMapLeve l>& texels) { | |
789 CLEAR_ERROR_BEFORE_ALLOC(&interface); | |
790 for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLe vel++) { | |
791 int width = texels[currentMipLevel].fWidth; | |
792 int height = texels[currentMipLevel].fHeight; | |
793 | |
794 // Make sure that the width and height that we pass to OpenGL | |
795 // is a multiple of the block size. | |
796 size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, width, height ); | |
797 | |
798 GL_ALLOC_CALL(&interface, | |
799 CompressedTexImage2D(target, | |
800 currentMipLevel, | |
801 internalFormat, | |
802 width, | |
803 height, | |
804 0, // border | |
805 SkToInt(dataSize), | |
806 texels[currentMipLevel].fTexelsOrOffs et)); | |
807 | |
808 GrGLenum error = check_alloc_error(desc, &interface); | |
809 if (error != GR_GL_NO_ERROR) { | |
810 return false; | |
811 } | |
812 } | |
813 | |
814 return true; | |
815 } | |
816 | |
817 /** | |
818 * After a texture is created, any state which was altered during its creation | |
819 * needs to be restored. | |
820 * | |
821 * @param interface The GL interface to use. | |
822 * @param caps The capabilities of the GL device. | |
823 * @param restoreGLRowLength Should the row length unpacking be restored? | |
824 * @param glFlipY Did GL flip the texture vertically? | |
825 */ | |
826 static void restore_pixelstore_state(const GrGLInterface& interface, const GrGLC aps& caps, | |
827 bool restoreGLRowLength, bool glFlipY) { | |
828 if (restoreGLRowLength) { | |
829 SkASSERT(caps.unpackRowLengthSupport()); | |
830 GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0)); | |
831 } | |
832 if (glFlipY) { | |
833 GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE)); | |
834 } | |
835 } | |
836 | |
726 bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc, | 837 bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc, |
727 GrGLenum target, | 838 GrGLenum target, |
728 UploadType uploadType, | 839 UploadType uploadType, |
729 int left, int top, int width, int height, | 840 int left, int top, int width, int height, |
730 GrPixelConfig dataConfig, | 841 GrPixelConfig dataConfig, |
731 const void* dataOrOffset, | 842 const SkTArray<SkMipMapLevel>& texels) { |
732 size_t rowBytes) { | |
733 SkASSERT(dataOrOffset || kNewTexture_UploadType == uploadType || | |
734 kTransfer_UploadType == uploadType); | |
735 | |
736 // If we're uploading compressed data then we should be using uploadCompress edTexData | 843 // If we're uploading compressed data then we should be using uploadCompress edTexData |
737 SkASSERT(!GrPixelConfigIsCompressed(dataConfig)); | 844 SkASSERT(!GrPixelConfigIsCompressed(dataConfig)); |
738 | 845 |
739 SkASSERT(this->caps()->isConfigTexturable(desc.fConfig)); | 846 SkASSERT(this->caps()->isConfigTexturable(desc.fConfig)); |
740 | 847 |
848 // texels is const. | |
849 // But we may need to flip the texture vertically to prepare it. | |
850 // Rather than flip in place and alter the incoming data, | |
851 // we allocate a new buffer to flip into. | |
852 // This means we need to make a non-const shallow copy of texels. | |
853 SkTArray<SkMipMapLevel> texelsShallowCopy(texels); | |
854 | |
855 for (int currentMipLevel = texelsShallowCopy.count() - 1; currentMipLevel >= 0; | |
856 currentMipLevel--) { | |
857 SkASSERT(texelsShallowCopy[currentMipLevel].fTexelsOrOffset || | |
858 kNewTexture_UploadType == uploadType || kTransfer_UploadType == uploadType); | |
859 } | |
860 | |
861 | |
862 const GrGLInterface* interface = this->glInterface(); | |
863 const GrGLCaps& caps = this->glCaps(); | |
864 | |
741 size_t bpp = GrBytesPerPixel(dataConfig); | 865 size_t bpp = GrBytesPerPixel(dataConfig); |
742 if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, & left, &top, | 866 for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); c urrentMipLevel++) { |
743 &width, &height, &dataOrOffset, & rowBytes)) { | 867 if (texelsShallowCopy[currentMipLevel].fTexelsOrOffset == nullptr) { |
744 return false; | 868 continue; |
869 } | |
870 | |
871 if (texelsShallowCopy[currentMipLevel].fHeight > SK_MaxS32 || | |
872 texelsShallowCopy[currentMipLevel].fWidth > SK_MaxS32) { | |
873 return false; | |
874 } | |
875 int currentMipHeight = texelsShallowCopy[currentMipLevel].fHeight; | |
876 int currentMipWidth = texelsShallowCopy[currentMipLevel].fWidth; | |
877 if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bp p, &left, &top, | |
878 ¤tMipWidth, | |
879 ¤tMipHeight, | |
880 &texelsShallowCopy[currentMipLeve l].fTexelsOrOffset, | |
881 &texelsShallowCopy[currentMipLeve l].fRowBytes)) { | |
882 return false; | |
883 } | |
884 if (currentMipWidth < 0 || currentMipHeight < 0) { | |
885 return false; | |
886 } | |
887 texelsShallowCopy[currentMipLevel].fWidth = currentMipWidth; | |
888 texelsShallowCopy[currentMipLevel].fHeight = currentMipHeight; | |
745 } | 889 } |
746 size_t trimRowBytes = width * bpp; | |
747 | |
748 // in case we need a temporary, trimmed copy of the src pixels | |
749 #if defined(GOOGLE3) | |
750 // Stack frame size is limited in GOOGLE3. | |
751 SkAutoSMalloc<64 * 128> tempStorage; | |
752 #else | |
753 SkAutoSMalloc<128 * 128> tempStorage; | |
754 #endif | |
755 | 890 |
756 // Internal format comes from the texture desc. | 891 // Internal format comes from the texture desc. |
757 GrGLenum internalFormat; | 892 GrGLenum internalFormat; |
758 // External format and type come from the upload data. | 893 // External format and type come from the upload data. |
759 GrGLenum externalFormat; | 894 GrGLenum externalFormat; |
760 GrGLenum externalType; | 895 GrGLenum externalType; |
761 if (!this->glCaps().getTexImageFormats(desc.fConfig, dataConfig, &internalFo rmat, | 896 if (!this->glCaps().getTexImageFormats(desc.fConfig, dataConfig, &internalFo rmat, |
762 &externalFormat, &externalType)) { | 897 &externalFormat, &externalType)) { |
763 return false; | 898 return false; |
764 } | 899 } |
765 /* | 900 /* |
766 * Check whether to allocate a temporary buffer for flipping y or | 901 * Check whether to allocate a temporary buffer for flipping y or |
767 * because our srcData has extra bytes past each row. If so, we need | 902 * because our srcData has extra bytes past each row. If so, we need |
768 * to trim those off here, since GL ES may not let us specify | 903 * to trim those off here, since GL ES may not let us specify |
769 * GL_UNPACK_ROW_LENGTH. | 904 * GL_UNPACK_ROW_LENGTH. |
770 */ | 905 */ |
771 bool restoreGLRowLength = false; | 906 bool restoreGLRowLength = false; |
772 bool swFlipY = false; | 907 bool swFlipY = false; |
773 bool glFlipY = false; | 908 bool glFlipY = false; |
774 if (dataOrOffset) { | 909 |
775 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { | 910 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { |
776 if (this->glCaps().unpackFlipYSupport()) { | 911 if (caps.unpackFlipYSupport()) { |
777 glFlipY = true; | 912 glFlipY = true; |
778 } else { | 913 } else { |
779 swFlipY = true; | 914 swFlipY = true; |
780 } | |
781 } | 915 } |
782 if (this->glCaps().unpackRowLengthSupport() && !swFlipY) { | 916 } |
917 | |
918 // in case we need a temporary, trimmed copy of the src pixels | |
919 SkAutoSMallocTexels tempStorage; | |
920 | |
921 // find the combined size of all the mip levels and the relative offset of | |
922 // each into the collective buffer | |
923 size_t combined_buffer_size = 0; | |
924 SkTArray<size_t> individual_mip_offsets(texelsShallowCopy.count()); | |
925 for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); c urrentMipLevel++) { | |
926 const size_t trimmedSize = texels[currentMipLevel].fWidth * bpp * | |
927 texelsShallowCopy[currentMipLevel].fHeight; | |
928 individual_mip_offsets.push_back(combined_buffer_size); | |
929 combined_buffer_size += trimmedSize; | |
930 } | |
931 char* buffer = (char*)tempStorage.reset(combined_buffer_size); | |
932 | |
933 for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count(); c urrentMipLevel++) { | |
934 if (texelsShallowCopy[currentMipLevel].fTexelsOrOffset == nullptr) { | |
935 continue; | |
936 } | |
937 | |
938 const size_t trimRowBytes = texelsShallowCopy[currentMipLevel].fWidth * bpp; | |
939 | |
940 /* | |
941 * check whether to allocate a temporary buffer for flipping y or | |
942 * because our srcData has extra bytes past each row. If so, we need | |
943 * to trim those off here, since GL ES may not let us specify | |
944 * GL_UNPACK_ROW_LENGTH. | |
945 */ | |
946 restoreGLRowLength = false; | |
947 | |
948 const size_t rowBytes = texelsShallowCopy[currentMipLevel].fRowBytes; | |
949 if (caps.unpackRowLengthSupport() && !swFlipY) { | |
783 // can't use this for flipping, only non-neg values allowed. :( | 950 // can't use this for flipping, only non-neg values allowed. :( |
784 if (rowBytes != trimRowBytes) { | 951 if (rowBytes != trimRowBytes) { |
785 GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp); | 952 GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp); |
786 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength)); | 953 GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLe ngth)); |
787 restoreGLRowLength = true; | 954 restoreGLRowLength = true; |
788 } | 955 } |
789 } else if (kTransfer_UploadType != uploadType) { | 956 } else if (kTransfer_UploadType != uploadType) { |
790 if (trimRowBytes != rowBytes || swFlipY) { | 957 if (trimRowBytes != rowBytes || swFlipY) { |
958 const int height = texelsShallowCopy[currentMipLevel].fHeight; | |
791 // copy data into our new storage, skipping the trailing bytes | 959 // copy data into our new storage, skipping the trailing bytes |
792 size_t trimSize = height * trimRowBytes; | 960 const char* src = (const char*)texelsShallowCopy[currentMipLevel ].fTexelsOrOffset; |
793 const char* src = (const char*)dataOrOffset; | 961 if (swFlipY && height >= 1) { |
794 if (swFlipY) { | |
795 src += (height - 1) * rowBytes; | 962 src += (height - 1) * rowBytes; |
796 } | 963 } |
797 char* dst = (char*)tempStorage.reset(trimSize); | 964 char* dst = buffer + individual_mip_offsets[currentMipLevel]; |
798 for (int y = 0; y < height; y++) { | 965 for (int y = 0; y < height; y++) { |
799 memcpy(dst, src, trimRowBytes); | 966 memcpy(dst, src, trimRowBytes); |
800 if (swFlipY) { | 967 if (swFlipY) { |
801 src -= rowBytes; | 968 src -= rowBytes; |
802 } else { | 969 } else { |
803 src += rowBytes; | 970 src += rowBytes; |
804 } | 971 } |
805 dst += trimRowBytes; | 972 dst += trimRowBytes; |
806 } | 973 } |
807 // now point data to our copied version | 974 // now point data to our copied version |
808 dataOrOffset = tempStorage.get(); | 975 texelsShallowCopy[currentMipLevel] = |
976 SkMipMapLevel(buffer + individual_mip_offsets[currentMipLeve l], | |
977 trimRowBytes, | |
978 texelsShallowCopy[currentMipLevel].fWidth, | |
979 texelsShallowCopy[currentMipLevel].fHeight); | |
809 } | 980 } |
810 } else { | 981 } else { |
811 return false; | 982 return false; |
812 } | 983 } |
813 if (glFlipY) { | 984 if (glFlipY) { |
814 GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE)); | 985 GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE)); |
815 } | 986 } |
816 GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, config_alignment(dataConfig) )); | 987 GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ALIGNMENT, |
988 config_alignment(desc.fConfig))); | |
817 } | 989 } |
990 | |
818 bool succeeded = true; | 991 bool succeeded = true; |
819 if (kNewTexture_UploadType == uploadType) { | 992 if (kNewTexture_UploadType == uploadType && |
820 if (dataOrOffset && | 993 0 == left && 0 == top && |
821 !(0 == left && 0 == top && desc.fWidth == width && desc.fHeight == h eight)) { | 994 desc.fWidth == width && desc.fHeight == height) { |
822 succeeded = false; | 995 allocate_and_populate_uncompressed_texture(desc, *interface, target, int ernalFormat, |
823 } else { | 996 externalFormat, externalType, texelsShallowCopy, |
824 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); | 997 &succeeded); |
825 GL_ALLOC_CALL(this->glInterface(), TexImage2D(target, 0, internalFor mat, desc.fWidth, | |
826 desc.fHeight, 0, exter nalFormat, | |
827 externalType, dataOrOf fset)); | |
828 GrGLenum error = check_alloc_error(desc, this->glInterface()); | |
829 if (error != GR_GL_NO_ERROR) { | |
830 succeeded = false; | |
831 } | |
832 } | |
833 } else { | 998 } else { |
834 if (swFlipY || glFlipY) { | 999 if (swFlipY || glFlipY) { |
835 top = desc.fHeight - (top + height); | 1000 top = desc.fHeight - (top + height); |
836 } | 1001 } |
837 GL_CALL(TexSubImage2D(target, | 1002 for (int currentMipLevel = 0; currentMipLevel < texelsShallowCopy.count( ); |
838 0, // level | 1003 currentMipLevel++) { |
839 left, top, | 1004 if (texelsShallowCopy[currentMipLevel].fTexelsOrOffset == nullptr) { |
840 width, height, | 1005 continue; |
841 externalFormat, externalType, dataOrOffset)); | 1006 } |
1007 | |
1008 GL_CALL(TexSubImage2D(target, | |
1009 currentMipLevel, | |
1010 left, top, | |
1011 texelsShallowCopy[currentMipLevel].fWidth, | |
1012 texelsShallowCopy[currentMipLevel].fHeight, | |
1013 externalFormat, externalType, | |
1014 texelsShallowCopy[currentMipLevel].fTexelsOrOf fset)); | |
1015 } | |
842 } | 1016 } |
843 | 1017 |
844 if (restoreGLRowLength) { | 1018 restore_pixelstore_state(*interface, caps, restoreGLRowLength, glFlipY); |
845 SkASSERT(this->glCaps().unpackRowLengthSupport()); | 1019 |
846 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0)); | |
847 } | |
848 if (glFlipY) { | |
849 GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE)); | |
850 } | |
851 return succeeded; | 1020 return succeeded; |
852 } | 1021 } |
853 | 1022 |
854 // TODO: This function is using a lot of wonky semantics like, if width == -1 | 1023 // TODO: This function is using a lot of wonky semantics like, if width == -1 |
855 // then set width = desc.fWdith ... blah. A better way to do it might be to | 1024 // then set width = desc.fWdith ... blah. A better way to do it might be to |
856 // create a CompressedTexData struct that takes a desc/ptr and figures out | 1025 // create a CompressedTexData struct that takes a desc/ptr and figures out |
857 // the proper upload semantics. Then users can construct this function how they | 1026 // the proper upload semantics. Then users can construct this function how they |
858 // see fit if they want to go against the "standard" way to do it. | 1027 // see fit if they want to go against the "standard" way to do it. |
859 bool GrGLGpu::uploadCompressedTexData(const GrSurfaceDesc& desc, | 1028 bool GrGLGpu::uploadCompressedTexData(const GrSurfaceDesc& desc, |
860 GrGLenum target, | 1029 GrGLenum target, |
861 const void* data, | 1030 const SkTArray<SkMipMapLevel>& texels, |
862 UploadType uploadType, | 1031 UploadType uploadType, |
863 int left, int top, int width, int height) { | 1032 int left, int top, int width, int height) { |
864 SkASSERT(this->caps()->isConfigTexturable(desc.fConfig)); | 1033 SkASSERT(this->caps()->isConfigTexturable(desc.fConfig)); |
865 SkASSERT(kTransfer_UploadType != uploadType && | 1034 SkASSERT(kTransfer_UploadType != uploadType && |
866 (data || kNewTexture_UploadType != uploadType)); | 1035 (texels[0].fTexelsOrOffset || kNewTexture_UploadType != uploadType) ); |
867 | 1036 |
868 // No support for software flip y, yet... | 1037 // No support for software flip y, yet... |
869 SkASSERT(kBottomLeft_GrSurfaceOrigin != desc.fOrigin); | 1038 SkASSERT(kBottomLeft_GrSurfaceOrigin != desc.fOrigin); |
870 | 1039 |
1040 const GrGLInterface* interface = this->glInterface(); | |
1041 const GrGLCaps& caps = this->glCaps(); | |
1042 | |
871 if (-1 == width) { | 1043 if (-1 == width) { |
872 width = desc.fWidth; | 1044 width = desc.fWidth; |
873 } | 1045 } |
874 #ifdef SK_DEBUG | 1046 #ifdef SK_DEBUG |
875 else { | 1047 else { |
876 SkASSERT(width <= desc.fWidth); | 1048 SkASSERT(width <= desc.fWidth); |
877 } | 1049 } |
878 #endif | 1050 #endif |
879 | 1051 |
880 if (-1 == height) { | 1052 if (-1 == height) { |
881 height = desc.fHeight; | 1053 height = desc.fHeight; |
882 } | 1054 } |
883 #ifdef SK_DEBUG | 1055 #ifdef SK_DEBUG |
884 else { | 1056 else { |
885 SkASSERT(height <= desc.fHeight); | 1057 SkASSERT(height <= desc.fHeight); |
886 } | 1058 } |
887 #endif | 1059 #endif |
888 | 1060 |
889 // Make sure that the width and height that we pass to OpenGL | |
890 // is a multiple of the block size. | |
891 size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, width, height); | |
892 | |
893 // We only need the internal format for compressed 2D textures. | 1061 // We only need the internal format for compressed 2D textures. |
894 GrGLenum internalFormat; | 1062 GrGLenum internalFormat; |
895 if (!this->glCaps().getCompressedTexImageFormats(desc.fConfig, &internalForm at)) { | 1063 if (!caps.getCompressedTexImageFormats(desc.fConfig, &internalFormat)) { |
896 return false; | 1064 return false; |
897 } | 1065 } |
898 | 1066 |
899 if (kNewTexture_UploadType == uploadType) { | 1067 if (kNewTexture_UploadType == uploadType) { |
900 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); | 1068 return allocate_and_populate_compressed_texture(desc, *interface, target , internalFormat, |
901 GL_ALLOC_CALL(this->glInterface(), | 1069 texels); |
902 CompressedTexImage2D(target, | |
903 0, // level | |
904 internalFormat, | |
905 width, height, | |
906 0, // border | |
907 SkToInt(dataSize), | |
908 data)); | |
909 GrGLenum error = check_alloc_error(desc, this->glInterface()); | |
910 if (error != GR_GL_NO_ERROR) { | |
911 return false; | |
912 } | |
913 } else { | 1070 } else { |
914 // Paletted textures can't be updated. | 1071 // Paletted textures can't be updated. |
915 if (GR_GL_PALETTE8_RGBA8 == internalFormat) { | 1072 if (GR_GL_PALETTE8_RGBA8 == internalFormat) { |
916 return false; | 1073 return false; |
917 } | 1074 } |
918 GL_CALL(CompressedTexSubImage2D(target, | 1075 for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentM ipLevel++) { |
919 0, // level | 1076 if (texels[currentMipLevel].fTexelsOrOffset == nullptr) { |
920 left, top, | 1077 continue; |
921 width, height, | 1078 } |
922 internalFormat, | 1079 |
923 SkToInt(dataSize), | 1080 // Make sure that the width and height that we pass to OpenGL |
924 data)); | 1081 // is a multiple of the block size. |
1082 size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, | |
1083 texels[currentMipLevel] .fWidth, | |
1084 texels[currentMipLevel] .fHeight); | |
1085 GL_CALL(CompressedTexSubImage2D(target, | |
1086 currentMipLevel, | |
1087 left, top, | |
1088 texels[currentMipLevel].fWidth, | |
1089 texels[currentMipLevel].fHeight, | |
1090 internalFormat, | |
1091 dataSize, | |
1092 texels[currentMipLevel].fTexelsOrOff set)); | |
1093 } | |
925 } | 1094 } |
926 | 1095 |
927 return true; | 1096 return true; |
928 } | 1097 } |
929 | 1098 |
930 static bool renderbuffer_storage_msaa(const GrGLContext& ctx, | 1099 static bool renderbuffer_storage_msaa(const GrGLContext& ctx, |
931 int sampleCount, | 1100 int sampleCount, |
932 GrGLenum format, | 1101 GrGLenum format, |
933 int width, int height) { | 1102 int width, int height) { |
934 CLEAR_ERROR_BEFORE_ALLOC(ctx.interface()); | 1103 CLEAR_ERROR_BEFORE_ALLOC(ctx.interface()); |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1078 // SkDEBUGFAIL("null texture"); | 1247 // SkDEBUGFAIL("null texture"); |
1079 return nullptr; | 1248 return nullptr; |
1080 } | 1249 } |
1081 | 1250 |
1082 #if 0 && defined(SK_DEBUG) | 1251 #if 0 && defined(SK_DEBUG) |
1083 static size_t as_size_t(int x) { | 1252 static size_t as_size_t(int x) { |
1084 return x; | 1253 return x; |
1085 } | 1254 } |
1086 #endif | 1255 #endif |
1087 | 1256 |
1257 static GrGLTexture::IDDesc generate_gl_texture(const GrGLInterface* interface, | |
1258 GrGpuResource::LifeCycle lifeCycl e) { | |
1259 GrGLTexture::IDDesc idDesc; | |
1260 idDesc.fInfo.fID = 0; | |
1261 GR_GL_CALL(interface, GenTextures(1, &idDesc.fInfo.fID)); | |
1262 idDesc.fLifeCycle = lifeCycle; | |
1263 // We only support GL_TEXTURE_2D at the moment. | |
1264 idDesc.fInfo.fTarget = GR_GL_TEXTURE_2D; | |
1265 return idDesc; | |
1266 } | |
1267 | |
1268 static GrGLTexture::TexParams set_initial_texture_params(const GrGLInterface* in terface, | |
1269 GrGLTexture::IDDesc idD esc) { | |
1270 // Some drivers like to know filter/wrap before seeing glTexImage2D. Some | |
1271 // drivers have a bug where an FBO won't be complete if it includes a | |
1272 // texture that is not mipmap complete (considering the filter in use). | |
1273 GrGLTexture::TexParams initialTexParams; | |
1274 // we only set a subset here so invalidate first | |
1275 initialTexParams.invalidate(); | |
1276 initialTexParams.fMinFilter = GR_GL_NEAREST; | |
1277 initialTexParams.fMagFilter = GR_GL_NEAREST; | |
1278 initialTexParams.fWrapS = GR_GL_CLAMP_TO_EDGE; | |
1279 initialTexParams.fWrapT = GR_GL_CLAMP_TO_EDGE; | |
1280 GR_GL_CALL(interface, TexParameteri(idDesc.fInfo.fTarget, | |
1281 GR_GL_TEXTURE_MAG_FILTER, | |
1282 initialTexParams.fMagFilter)); | |
1283 GR_GL_CALL(interface, TexParameteri(idDesc.fInfo.fTarget, | |
1284 GR_GL_TEXTURE_MIN_FILTER, | |
1285 initialTexParams.fMinFilter)); | |
1286 GR_GL_CALL(interface, TexParameteri(idDesc.fInfo.fTarget, | |
1287 GR_GL_TEXTURE_WRAP_S, | |
1288 initialTexParams.fWrapS)); | |
1289 GR_GL_CALL(interface, TexParameteri(idDesc.fInfo.fTarget, | |
1290 GR_GL_TEXTURE_WRAP_T, | |
1291 initialTexParams.fWrapT)); | |
1292 return initialTexParams; | |
1293 } | |
1294 | |
1088 GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc, | 1295 GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc, |
1089 GrGpuResource::LifeCycle lifeCycle, | 1296 GrGpuResource::LifeCycle lifeCycle, |
1090 const void* srcData, size_t rowBytes) { | 1297 const SkTArray<SkMipMapLevel>& texels) { |
1091 // We fail if the MSAA was requested and is not available. | 1298 // We fail if the MSAA was requested and is not available. |
1092 if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleC nt) { | 1299 if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleC nt) { |
1093 //SkDebugf("MSAA RT requested but not supported on this platform."); | 1300 //SkDebugf("MSAA RT requested but not supported on this platform."); |
1094 return return_null_texture(); | 1301 return return_null_texture(); |
1095 } | 1302 } |
1096 | 1303 |
1097 bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag); | 1304 bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag); |
1098 | 1305 |
1099 GrGLTexture::IDDesc idDesc; | 1306 GrGLTexture::IDDesc idDesc = generate_gl_texture(this->glInterface(), lifeCy cle); |
1100 idDesc.fInfo.fID = 0; | |
1101 GL_CALL(GenTextures(1, &idDesc.fInfo.fID)); | |
1102 idDesc.fLifeCycle = lifeCycle; | |
1103 // We only support GL_TEXTURE_2D at the moment. | |
1104 idDesc.fInfo.fTarget = GR_GL_TEXTURE_2D; | |
1105 | |
1106 if (!idDesc.fInfo.fID) { | 1307 if (!idDesc.fInfo.fID) { |
1107 return return_null_texture(); | 1308 return return_null_texture(); |
1108 } | 1309 } |
1109 | 1310 |
1110 this->setScratchTextureUnit(); | 1311 this->setScratchTextureUnit(); |
1111 GL_CALL(BindTexture(idDesc.fInfo.fTarget, idDesc.fInfo.fID)); | 1312 GL_CALL(BindTexture(idDesc.fInfo.fTarget, idDesc.fInfo.fID)); |
1112 | 1313 |
1113 if (renderTarget && this->glCaps().textureUsageSupport()) { | 1314 if (renderTarget && this->glCaps().textureUsageSupport()) { |
1114 // provides a hint about how this texture will be used | 1315 // provides a hint about how this texture will be used |
1115 GL_CALL(TexParameteri(idDesc.fInfo.fTarget, | 1316 GL_CALL(TexParameteri(idDesc.fInfo.fTarget, |
1116 GR_GL_TEXTURE_USAGE, | 1317 GR_GL_TEXTURE_USAGE, |
1117 GR_GL_FRAMEBUFFER_ATTACHMENT)); | 1318 GR_GL_FRAMEBUFFER_ATTACHMENT)); |
1118 } | 1319 } |
1119 | 1320 |
1120 // Some drivers like to know filter/wrap before seeing glTexImage2D. Some | 1321 GrGLTexture::TexParams initialTexParams = set_initial_texture_params(this->g lInterface(), |
1121 // drivers have a bug where an FBO won't be complete if it includes a | 1322 idDesc) ; |
1122 // texture that is not mipmap complete (considering the filter in use). | 1323 |
1123 GrGLTexture::TexParams initialTexParams; | |
1124 // we only set a subset here so invalidate first | |
1125 initialTexParams.invalidate(); | |
1126 initialTexParams.fMinFilter = GR_GL_NEAREST; | |
1127 initialTexParams.fMagFilter = GR_GL_NEAREST; | |
1128 initialTexParams.fWrapS = GR_GL_CLAMP_TO_EDGE; | |
1129 initialTexParams.fWrapT = GR_GL_CLAMP_TO_EDGE; | |
1130 GL_CALL(TexParameteri(idDesc.fInfo.fTarget, | |
1131 GR_GL_TEXTURE_MAG_FILTER, | |
1132 initialTexParams.fMagFilter)); | |
1133 GL_CALL(TexParameteri(idDesc.fInfo.fTarget, | |
1134 GR_GL_TEXTURE_MIN_FILTER, | |
1135 initialTexParams.fMinFilter)); | |
1136 GL_CALL(TexParameteri(idDesc.fInfo.fTarget, | |
1137 GR_GL_TEXTURE_WRAP_S, | |
1138 initialTexParams.fWrapS)); | |
1139 GL_CALL(TexParameteri(idDesc.fInfo.fTarget, | |
1140 GR_GL_TEXTURE_WRAP_T, | |
1141 initialTexParams.fWrapT)); | |
1142 if (!this->uploadTexData(desc, idDesc.fInfo.fTarget, kNewTexture_UploadType, 0, 0, | 1324 if (!this->uploadTexData(desc, idDesc.fInfo.fTarget, kNewTexture_UploadType, 0, 0, |
1143 desc.fWidth, desc.fHeight, | 1325 desc.fWidth, desc.fHeight, |
1144 desc.fConfig, srcData, rowBytes)) { | 1326 desc.fConfig, texels)) { |
1145 GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID)); | 1327 GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID)); |
1146 return return_null_texture(); | 1328 return return_null_texture(); |
1147 } | 1329 } |
1148 | 1330 |
1149 GrGLTexture* tex; | 1331 GrGLTexture* tex; |
1150 if (renderTarget) { | 1332 if (renderTarget) { |
1151 // unbind the texture from the texture unit before binding it to the fra me buffer | 1333 // unbind the texture from the texture unit before binding it to the fra me buffer |
1152 GL_CALL(BindTexture(idDesc.fInfo.fTarget, 0)); | 1334 GL_CALL(BindTexture(idDesc.fInfo.fTarget, 0)); |
1153 GrGLRenderTarget::IDDesc rtIDDesc; | 1335 GrGLRenderTarget::IDDesc rtIDDesc; |
1154 | 1336 |
1155 if (!this->createRenderTargetObjects(desc, lifeCycle, idDesc.fInfo, &rtI DDesc)) { | 1337 if (!this->createRenderTargetObjects(desc, lifeCycle, idDesc.fInfo, &rtI DDesc)) { |
1156 GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID)); | 1338 GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID)); |
1157 return return_null_texture(); | 1339 return return_null_texture(); |
1158 } | 1340 } |
1159 tex = new GrGLTextureRenderTarget(this, desc, idDesc, rtIDDesc); | 1341 tex = new GrGLTextureRenderTarget(this, desc, idDesc, rtIDDesc); |
1160 } else { | 1342 } else { |
1161 tex = new GrGLTexture(this, desc, idDesc); | 1343 bool wasMipMapDataProvided = false; |
1344 if (texels.count() > 1) { | |
1345 wasMipMapDataProvided = true; | |
1346 } | |
1347 tex = new GrGLTexture(this, desc, idDesc, wasMipMapDataProvided); | |
1162 } | 1348 } |
1163 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); | 1349 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); |
1164 #ifdef TRACE_TEXTURE_CREATION | 1350 #ifdef TRACE_TEXTURE_CREATION |
1165 SkDebugf("--- new texture [%d] size=(%d %d) config=%d\n", | 1351 SkDebugf("--- new texture [%d] size=(%d %d) config=%d\n", |
1166 glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig); | 1352 glTexDesc.fInfo.fID, desc.fWidth, desc.fHeight, desc.fConfig); |
1167 #endif | 1353 #endif |
1168 return tex; | 1354 return tex; |
1169 } | 1355 } |
1170 | 1356 |
1171 GrTexture* GrGLGpu::onCreateCompressedTexture(const GrSurfaceDesc& desc, | 1357 GrTexture* GrGLGpu::onCreateCompressedTexture(const GrSurfaceDesc& desc, |
1172 GrGpuResource::LifeCycle lifeCycle , | 1358 GrGpuResource::LifeCycle lifeCycle , |
1173 const void* srcData) { | 1359 const SkTArray<SkMipMapLevel>& tex els) { |
1174 // Make sure that we're not flipping Y. | 1360 // Make sure that we're not flipping Y. |
1175 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { | 1361 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { |
1176 return return_null_texture(); | 1362 return return_null_texture(); |
1177 } | 1363 } |
1178 | 1364 |
1179 GrGLTexture::IDDesc idDesc; | 1365 GrGLTexture::IDDesc idDesc = generate_gl_texture(this->glInterface(), lifeCy cle); |
1180 idDesc.fInfo.fID = 0; | |
1181 GL_CALL(GenTextures(1, &idDesc.fInfo.fID)); | |
1182 idDesc.fLifeCycle = lifeCycle; | |
1183 // We only support GL_TEXTURE_2D at the moment. | |
1184 idDesc.fInfo.fTarget = GR_GL_TEXTURE_2D; | |
1185 | |
1186 if (!idDesc.fInfo.fID) { | 1366 if (!idDesc.fInfo.fID) { |
1187 return return_null_texture(); | 1367 return return_null_texture(); |
1188 } | 1368 } |
1189 | 1369 |
1190 this->setScratchTextureUnit(); | 1370 this->setScratchTextureUnit(); |
1191 GL_CALL(BindTexture(idDesc.fInfo.fTarget, idDesc.fInfo.fID)); | 1371 GL_CALL(BindTexture(idDesc.fInfo.fTarget, idDesc.fInfo.fID)); |
1192 | 1372 |
1193 // Some drivers like to know filter/wrap before seeing glTexImage2D. Some | 1373 GrGLTexture::TexParams initialTexParams = set_initial_texture_params(this->g lInterface(), |
1194 // drivers have a bug where an FBO won't be complete if it includes a | 1374 idDesc) ; |
1195 // texture that is not mipmap complete (considering the filter in use). | |
1196 GrGLTexture::TexParams initialTexParams; | |
1197 // we only set a subset here so invalidate first | |
1198 initialTexParams.invalidate(); | |
1199 initialTexParams.fMinFilter = GR_GL_NEAREST; | |
1200 initialTexParams.fMagFilter = GR_GL_NEAREST; | |
1201 initialTexParams.fWrapS = GR_GL_CLAMP_TO_EDGE; | |
1202 initialTexParams.fWrapT = GR_GL_CLAMP_TO_EDGE; | |
1203 GL_CALL(TexParameteri(idDesc.fInfo.fTarget, | |
1204 GR_GL_TEXTURE_MAG_FILTER, | |
1205 initialTexParams.fMagFilter)); | |
1206 GL_CALL(TexParameteri(idDesc.fInfo.fTarget, | |
1207 GR_GL_TEXTURE_MIN_FILTER, | |
1208 initialTexParams.fMinFilter)); | |
1209 GL_CALL(TexParameteri(idDesc.fInfo.fTarget, | |
1210 GR_GL_TEXTURE_WRAP_S, | |
1211 initialTexParams.fWrapS)); | |
1212 GL_CALL(TexParameteri(idDesc.fInfo.fTarget, | |
1213 GR_GL_TEXTURE_WRAP_T, | |
1214 initialTexParams.fWrapT)); | |
1215 | 1375 |
1216 if (!this->uploadCompressedTexData(desc, idDesc.fInfo.fTarget, srcData)) { | 1376 if (!this->uploadCompressedTexData(desc, idDesc.fInfo.fTarget, texels)) { |
1217 GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID)); | 1377 GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID)); |
1218 return return_null_texture(); | 1378 return return_null_texture(); |
1219 } | 1379 } |
1220 | 1380 |
1221 GrGLTexture* tex; | 1381 GrGLTexture* tex; |
1222 tex = new GrGLTexture(this, desc, idDesc); | 1382 tex = new GrGLTexture(this, desc, idDesc); |
1223 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); | 1383 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); |
1224 #ifdef TRACE_TEXTURE_CREATION | 1384 #ifdef TRACE_TEXTURE_CREATION |
1225 SkDebugf("--- new compressed texture [%d] size=(%d %d) config=%d\n", | 1385 SkDebugf("--- new compressed texture [%d] size=(%d %d) config=%d\n", |
1226 glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig); | 1386 glTexDesc.fInfo.fID, desc.fWidth, desc.fHeight, desc.fConfig); |
1227 #endif | 1387 #endif |
1228 return tex; | 1388 return tex; |
1229 } | 1389 } |
1230 | 1390 |
1231 namespace { | 1391 namespace { |
1232 | 1392 |
1233 const GrGLuint kUnknownBitCount = GrGLStencilAttachment::kUnknownBitCount; | 1393 const GrGLuint kUnknownBitCount = GrGLStencilAttachment::kUnknownBitCount; |
1234 | 1394 |
1235 void inline get_stencil_rb_sizes(const GrGLInterface* gl, | 1395 void inline get_stencil_rb_sizes(const GrGLInterface* gl, |
1236 GrGLStencilAttachment::Format* format) { | 1396 GrGLStencilAttachment::Format* format) { |
(...skipping 1329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2566 | 2726 |
2567 if (GrTextureParams::kMipMap_FilterMode == filterMode) { | 2727 if (GrTextureParams::kMipMap_FilterMode == filterMode) { |
2568 if (!this->caps()->mipMapSupport() || GrPixelConfigIsCompressed(texture- >config())) { | 2728 if (!this->caps()->mipMapSupport() || GrPixelConfigIsCompressed(texture- >config())) { |
2569 filterMode = GrTextureParams::kBilerp_FilterMode; | 2729 filterMode = GrTextureParams::kBilerp_FilterMode; |
2570 } | 2730 } |
2571 } | 2731 } |
2572 | 2732 |
2573 newTexParams.fMinFilter = glMinFilterModes[filterMode]; | 2733 newTexParams.fMinFilter = glMinFilterModes[filterMode]; |
2574 newTexParams.fMagFilter = glMagFilterModes[filterMode]; | 2734 newTexParams.fMagFilter = glMagFilterModes[filterMode]; |
2575 | 2735 |
2576 if (GrTextureParams::kMipMap_FilterMode == filterMode && | 2736 if (GrTextureParams::kMipMap_FilterMode == filterMode) { |
2577 texture->texturePriv().mipMapsAreDirty()) { | 2737 if (texture->texturePriv().mipMapsAreDirty()) { |
2578 GL_CALL(GenerateMipmap(target)); | 2738 GL_CALL(GenerateMipmap(target)); |
2579 texture->texturePriv().dirtyMipMaps(false); | 2739 texture->texturePriv().dirtyMipMaps(false); |
2740 texture->texturePriv().setMaxMipMapLevel(SkMipMapLevelCount(texture- >width(), | |
2741 texture- >height())); | |
2742 } | |
2743 if (texture->texturePriv().hasMipMaps()) { | |
2744 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MIN_LOD, 0)); | |
bsalomon
2016/01/20 14:21:44
Should we be setting this on every draw? Maybe sto
cblume
2016/01/21 23:08:50
I have updated this to now only call when the max
| |
2745 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_BASE_LEVEL, 0)); | |
2746 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAX_LOD, | |
2747 static_cast<float>(texture->texturePriv().maxM ipMapLevel()))); | |
2748 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAX_LEVEL, | |
2749 texture->texturePriv().maxMipMapLevel())); | |
2750 } | |
2580 } | 2751 } |
2581 | 2752 |
2582 newTexParams.fWrapS = tile_to_gl_wrap(params.getTileModeX()); | 2753 newTexParams.fWrapS = tile_to_gl_wrap(params.getTileModeX()); |
2583 newTexParams.fWrapT = tile_to_gl_wrap(params.getTileModeY()); | 2754 newTexParams.fWrapT = tile_to_gl_wrap(params.getTileModeY()); |
2584 get_tex_param_swizzle(texture->config(), this->glCaps(), newTexParams.fSwizz leRGBA); | 2755 get_tex_param_swizzle(texture->config(), this->glCaps(), newTexParams.fSwizz leRGBA); |
2585 if (setAll || newTexParams.fMagFilter != oldTexParams.fMagFilter) { | 2756 if (setAll || newTexParams.fMagFilter != oldTexParams.fMagFilter) { |
2586 this->setTextureUnit(unitIdx); | 2757 this->setTextureUnit(unitIdx); |
2587 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAG_FILTER, newTexParams.fMa gFilter)); | 2758 GL_CALL(TexParameteri(target, GR_GL_TEXTURE_MAG_FILTER, newTexParams.fMa gFilter)); |
2588 } | 2759 } |
2589 if (setAll || newTexParams.fMinFilter != oldTexParams.fMinFilter) { | 2760 if (setAll || newTexParams.fMinFilter != oldTexParams.fMinFilter) { |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2775 viewport->fWidth = surface->width(); | 2946 viewport->fWidth = surface->width(); |
2776 viewport->fHeight = surface->height(); | 2947 viewport->fHeight = surface->height(); |
2777 } else { | 2948 } else { |
2778 fStats.incRenderTargetBinds(); | 2949 fStats.incRenderTargetBinds(); |
2779 GR_GL_CALL(this->glInterface(), BindFramebuffer(fboTarget, rt->renderFBO ID())); | 2950 GR_GL_CALL(this->glInterface(), BindFramebuffer(fboTarget, rt->renderFBO ID())); |
2780 *viewport = rt->getViewport(); | 2951 *viewport = rt->getViewport(); |
2781 } | 2952 } |
2782 } | 2953 } |
2783 | 2954 |
2784 void GrGLGpu::unbindTextureFBOForCopy(GrGLenum fboTarget, GrSurface* surface) { | 2955 void GrGLGpu::unbindTextureFBOForCopy(GrGLenum fboTarget, GrSurface* surface) { |
2785 // bindSurfaceFBOForCopy temporarily binds textures that are not render targ ets to | 2956 // bindSurfaceFBOForCopy temporarily binds textures that are not render targ ets to |
2786 if (!surface->asRenderTarget()) { | 2957 if (!surface->asRenderTarget()) { |
2787 SkASSERT(surface->asTexture()); | 2958 SkASSERT(surface->asTexture()); |
2788 GrGLenum textureTarget = static_cast<GrGLTexture*>(surface->asTexture()) ->target(); | 2959 GrGLenum textureTarget = static_cast<GrGLTexture*>(surface->asTexture()) ->target(); |
2789 GR_GL_CALL(this->glInterface(), FramebufferTexture2D(fboTarget, | 2960 GR_GL_CALL(this->glInterface(), FramebufferTexture2D(fboTarget, |
2790 GR_GL_COLOR_ATTACHM ENT0, | 2961 GR_GL_COLOR_ATTACHM ENT0, |
2791 textureTarget, | 2962 textureTarget, |
2792 0, | 2963 0, |
2793 0)); | 2964 0)); |
2794 } | 2965 } |
2795 } | 2966 } |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2859 // None of our copy methods can handle a swizzle. TODO: Make copySurfaceAsDr aw handle the | 3030 // None of our copy methods can handle a swizzle. TODO: Make copySurfaceAsDr aw handle the |
2860 // swizzle. | 3031 // swizzle. |
2861 if (this->glCaps().glslCaps()->configOutputSwizzle(src->config()) != | 3032 if (this->glCaps().glslCaps()->configOutputSwizzle(src->config()) != |
2862 this->glCaps().glslCaps()->configOutputSwizzle(dst->config())) { | 3033 this->glCaps().glslCaps()->configOutputSwizzle(dst->config())) { |
2863 return false; | 3034 return false; |
2864 } | 3035 } |
2865 if (src->asTexture() && dst->asRenderTarget()) { | 3036 if (src->asTexture() && dst->asRenderTarget()) { |
2866 this->copySurfaceAsDraw(dst, src, srcRect, dstPoint); | 3037 this->copySurfaceAsDraw(dst, src, srcRect, dstPoint); |
2867 return true; | 3038 return true; |
2868 } | 3039 } |
2869 | 3040 |
2870 if (can_copy_texsubimage(dst, src, this)) { | 3041 if (can_copy_texsubimage(dst, src, this)) { |
2871 this->copySurfaceAsCopyTexSubImage(dst, src, srcRect, dstPoint); | 3042 this->copySurfaceAsCopyTexSubImage(dst, src, srcRect, dstPoint); |
2872 return true; | 3043 return true; |
2873 } | 3044 } |
2874 | 3045 |
2875 if (can_blit_framebuffer(dst, src, this)) { | 3046 if (can_blit_framebuffer(dst, src, this)) { |
2876 return this->copySurfaceAsBlitFramebuffer(dst, src, srcRect, dstPoint); | 3047 return this->copySurfaceAsBlitFramebuffer(dst, src, srcRect, dstPoint); |
2877 } | 3048 } |
2878 | 3049 |
2879 return false; | 3050 return false; |
(...skipping 30 matching lines...) Expand all Loading... | |
2910 | 3081 |
2911 SkString vshaderTxt(version); | 3082 SkString vshaderTxt(version); |
2912 aVertex.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); | 3083 aVertex.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); |
2913 vshaderTxt.append(";"); | 3084 vshaderTxt.append(";"); |
2914 uTexCoordXform.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); | 3085 uTexCoordXform.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); |
2915 vshaderTxt.append(";"); | 3086 vshaderTxt.append(";"); |
2916 uPosXform.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); | 3087 uPosXform.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); |
2917 vshaderTxt.append(";"); | 3088 vshaderTxt.append(";"); |
2918 vTexCoord.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); | 3089 vTexCoord.appendDecl(this->glCaps().glslCaps(), &vshaderTxt); |
2919 vshaderTxt.append(";"); | 3090 vshaderTxt.append(";"); |
2920 | 3091 |
2921 vshaderTxt.append( | 3092 vshaderTxt.append( |
2922 "// Copy Program VS\n" | 3093 "// Copy Program VS\n" |
2923 "void main() {" | 3094 "void main() {" |
2924 " v_texCoord = a_vertex.xy * u_texCoordXform.xy + u_texCoordXform.z w;" | 3095 " v_texCoord = a_vertex.xy * u_texCoordXform.xy + u_texCoordXform.z w;" |
2925 " gl_Position.xy = a_vertex * u_posXform.xy + u_posXform.zw;" | 3096 " gl_Position.xy = a_vertex * u_posXform.xy + u_posXform.zw;" |
2926 " gl_Position.zw = vec2(0, 1);" | 3097 " gl_Position.zw = vec2(0, 1);" |
2927 "}" | 3098 "}" |
2928 ); | 3099 ); |
2929 | 3100 |
2930 SkString fshaderTxt(version); | 3101 SkString fshaderTxt(version); |
(...skipping 18 matching lines...) Expand all Loading... | |
2949 fsOutName = "gl_FragColor"; | 3120 fsOutName = "gl_FragColor"; |
2950 } | 3121 } |
2951 fshaderTxt.appendf( | 3122 fshaderTxt.appendf( |
2952 "// Copy Program FS\n" | 3123 "// Copy Program FS\n" |
2953 "void main() {" | 3124 "void main() {" |
2954 " %s = %s(u_texture, v_texCoord);" | 3125 " %s = %s(u_texture, v_texCoord);" |
2955 "}", | 3126 "}", |
2956 fsOutName, | 3127 fsOutName, |
2957 GrGLSLTexture2DFunctionName(kVec2f_GrSLType, kSamplerTypes[i], this- >glslGeneration()) | 3128 GrGLSLTexture2DFunctionName(kVec2f_GrSLType, kSamplerTypes[i], this- >glslGeneration()) |
2958 ); | 3129 ); |
2959 | 3130 |
2960 GL_CALL_RET(fCopyPrograms[i].fProgram, CreateProgram()); | 3131 GL_CALL_RET(fCopyPrograms[i].fProgram, CreateProgram()); |
2961 const char* str; | 3132 const char* str; |
2962 GrGLint length; | 3133 GrGLint length; |
2963 | 3134 |
2964 str = vshaderTxt.c_str(); | 3135 str = vshaderTxt.c_str(); |
2965 length = SkToInt(vshaderTxt.size()); | 3136 length = SkToInt(vshaderTxt.size()); |
2966 GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms [i].fProgram, | 3137 GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms [i].fProgram, |
2967 GR_GL_VERTEX_SHADER, &str, &length, 1, | 3138 GR_GL_VERTEX_SHADER, &str, &length, 1, |
2968 &fStats); | 3139 &fStats); |
2969 | 3140 |
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3484 this->setVertexArrayID(gpu, 0); | 3655 this->setVertexArrayID(gpu, 0); |
3485 } | 3656 } |
3486 int attrCount = gpu->glCaps().maxVertexAttributes(); | 3657 int attrCount = gpu->glCaps().maxVertexAttributes(); |
3487 if (fDefaultVertexArrayAttribState.count() != attrCount) { | 3658 if (fDefaultVertexArrayAttribState.count() != attrCount) { |
3488 fDefaultVertexArrayAttribState.resize(attrCount); | 3659 fDefaultVertexArrayAttribState.resize(attrCount); |
3489 } | 3660 } |
3490 attribState = &fDefaultVertexArrayAttribState; | 3661 attribState = &fDefaultVertexArrayAttribState; |
3491 } | 3662 } |
3492 return attribState; | 3663 return attribState; |
3493 } | 3664 } |
OLD | NEW |