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" |
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
466 | 466 |
467 int maxSize = this->caps()->maxTextureSize(); | 467 int maxSize = this->caps()->maxTextureSize(); |
468 if (desc.fWidth > maxSize || desc.fHeight > maxSize) { | 468 if (desc.fWidth > maxSize || desc.fHeight > maxSize) { |
469 return NULL; | 469 return NULL; |
470 } | 470 } |
471 | 471 |
472 GrGLTexture::IDDesc idDesc; | 472 GrGLTexture::IDDesc idDesc; |
473 GrSurfaceDesc surfDesc; | 473 GrSurfaceDesc surfDesc; |
474 | 474 |
475 idDesc.fTextureID = static_cast<GrGLuint>(desc.fTextureHandle); | 475 idDesc.fTextureID = static_cast<GrGLuint>(desc.fTextureHandle); |
476 | 476 |
477 switch (ownership) { | 477 switch (ownership) { |
478 case kAdopt_GrWrapOwnership: | 478 case kAdopt_GrWrapOwnership: |
479 idDesc.fLifeCycle = GrGpuResource::kAdopted_LifeCycle; | 479 idDesc.fLifeCycle = GrGpuResource::kAdopted_LifeCycle; |
480 break; | 480 break; |
481 case kBorrow_GrWrapOwnership: | 481 case kBorrow_GrWrapOwnership: |
482 idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle; | 482 idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle; |
483 break; | 483 break; |
484 } | 484 } |
485 | 485 |
486 // next line relies on GrBackendTextureDesc's flags matching GrTexture's | 486 // next line relies on GrBackendTextureDesc's flags matching GrTexture's |
487 surfDesc.fFlags = (GrSurfaceFlags) desc.fFlags; | 487 surfDesc.fFlags = (GrSurfaceFlags) desc.fFlags; |
488 surfDesc.fWidth = desc.fWidth; | 488 surfDesc.fWidth = desc.fWidth; |
489 surfDesc.fHeight = desc.fHeight; | 489 surfDesc.fHeight = desc.fHeight; |
490 surfDesc.fConfig = desc.fConfig; | 490 surfDesc.fConfig = desc.fConfig; |
491 surfDesc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount()
); | 491 surfDesc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount()
); |
492 bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFla
g); | 492 bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFla
g); |
493 // FIXME: this should be calling resolve_origin(), but Chrome code is curre
ntly | 493 // FIXME: this should be calling resolve_origin(), but Chrome code is curre
ntly |
494 // assuming the old behaviour, which is that backend textures are always | 494 // assuming the old behaviour, which is that backend textures are always |
(...skipping 29 matching lines...) Expand all Loading... |
524 idDesc.fRTFBOID = static_cast<GrGLuint>(wrapDesc.fRenderTargetHandle); | 524 idDesc.fRTFBOID = static_cast<GrGLuint>(wrapDesc.fRenderTargetHandle); |
525 idDesc.fMSColorRenderbufferID = 0; | 525 idDesc.fMSColorRenderbufferID = 0; |
526 idDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID; | 526 idDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID; |
527 switch (ownership) { | 527 switch (ownership) { |
528 case kAdopt_GrWrapOwnership: | 528 case kAdopt_GrWrapOwnership: |
529 idDesc.fLifeCycle = GrGpuResource::kAdopted_LifeCycle; | 529 idDesc.fLifeCycle = GrGpuResource::kAdopted_LifeCycle; |
530 break; | 530 break; |
531 case kBorrow_GrWrapOwnership: | 531 case kBorrow_GrWrapOwnership: |
532 idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle; | 532 idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle; |
533 break; | 533 break; |
534 } | 534 } |
535 idDesc.fSampleConfig = GrRenderTarget::kUnified_SampleConfig; | 535 idDesc.fSampleConfig = GrRenderTarget::kUnified_SampleConfig; |
536 | 536 |
537 GrSurfaceDesc desc; | 537 GrSurfaceDesc desc; |
538 desc.fConfig = wrapDesc.fConfig; | 538 desc.fConfig = wrapDesc.fConfig; |
539 desc.fFlags = kCheckAllocation_GrSurfaceFlag; | 539 desc.fFlags = kCheckAllocation_GrSurfaceFlag; |
540 desc.fWidth = wrapDesc.fWidth; | 540 desc.fWidth = wrapDesc.fWidth; |
541 desc.fHeight = wrapDesc.fHeight; | 541 desc.fHeight = wrapDesc.fHeight; |
542 desc.fSampleCnt = SkTMin(wrapDesc.fSampleCnt, this->caps()->maxSampleCount()
); | 542 desc.fSampleCnt = SkTMin(wrapDesc.fSampleCnt, this->caps()->maxSampleCount()
); |
543 desc.fOrigin = resolve_origin(wrapDesc.fOrigin, true); | 543 desc.fOrigin = resolve_origin(wrapDesc.fOrigin, true); |
544 | 544 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
624 | 624 |
625 static inline GrGLenum check_alloc_error(const GrSurfaceDesc& desc, | 625 static inline GrGLenum check_alloc_error(const GrSurfaceDesc& desc, |
626 const GrGLInterface* interface) { | 626 const GrGLInterface* interface) { |
627 if (SkToBool(desc.fFlags & kCheckAllocation_GrSurfaceFlag)) { | 627 if (SkToBool(desc.fFlags & kCheckAllocation_GrSurfaceFlag)) { |
628 return GR_GL_GET_ERROR(interface); | 628 return GR_GL_GET_ERROR(interface); |
629 } else { | 629 } else { |
630 return CHECK_ALLOC_ERROR(interface); | 630 return CHECK_ALLOC_ERROR(interface); |
631 } | 631 } |
632 } | 632 } |
633 | 633 |
634 bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc, | 634 static bool can_use_tex_storage(const GrGLCaps& caps, const GrGLStandard& standa
rd, |
635 bool isNewTexture, | 635 const GrSurfaceDesc& desc) { |
636 int left, int top, int width, int height, | 636 bool useTexStorage = caps.texStorageSupport(); |
637 GrPixelConfig dataConfig, | 637 if (useTexStorage && kGL_GrGLStandard == standard) { |
638 const void* data, | |
639 size_t rowBytes) { | |
640 SkASSERT(data || isNewTexture); | |
641 | |
642 // If we're uploading compressed data then we should be using uploadCompress
edTexData | |
643 SkASSERT(!GrPixelConfigIsCompressed(dataConfig)); | |
644 | |
645 size_t bpp = GrBytesPerPixel(dataConfig); | |
646 if (!adjust_pixel_ops_params(desc.fWidth, desc.fHeight, bpp, &left, &top, | |
647 &width, &height, &data, &rowBytes)) { | |
648 return false; | |
649 } | |
650 size_t trimRowBytes = width * bpp; | |
651 | |
652 // in case we need a temporary, trimmed copy of the src pixels | |
653 SkAutoSMalloc<128 * 128> tempStorage; | |
654 | |
655 // We currently lazily create MIPMAPs when the we see a draw with | |
656 // GrTextureParams::kMipMap_FilterMode. Using texture storage requires that
the | |
657 // MIP levels are all created when the texture is created. So for now we don
't use | |
658 // texture storage. | |
659 bool useTexStorage = false && | |
660 isNewTexture && | |
661 this->glCaps().texStorageSupport(); | |
662 | |
663 if (useTexStorage && kGL_GrGLStandard == this->glStandard()) { | |
664 // 565 is not a sized internal format on desktop GL. So on desktop with | 638 // 565 is not a sized internal format on desktop GL. So on desktop with |
665 // 565 we always use an unsized internal format to let the system pick | 639 // 565 we always use an unsized internal format to let the system pick |
666 // the best sized format to convert the 565 data to. Since TexStorage | 640 // the best sized format to convert the 565 data to. Since TexStorage |
667 // only allows sized internal formats we will instead use TexImage2D. | 641 // only allows sized internal formats we will instead use TexImage2D. |
668 useTexStorage = desc.fConfig != kRGB_565_GrPixelConfig; | 642 useTexStorage = desc.fConfig != kRGB_565_GrPixelConfig; |
669 } | 643 } |
670 | 644 |
671 GrGLenum internalFormat = 0x0; // suppress warning | 645 return useTexStorage; |
672 GrGLenum externalFormat = 0x0; // suppress warning | 646 } |
673 GrGLenum externalType = 0x0; // suppress warning | 647 |
674 | 648 static bool can_use_sized_format(bool useTexStorage, const GrGLCaps& caps, |
| 649 const GrGLStandard& standard, const GrGLVersion
& version, |
| 650 GrPixelConfig dataConfig) { |
675 // glTexStorage requires sized internal formats on both desktop and ES. ES2
requires an unsized | 651 // glTexStorage requires sized internal formats on both desktop and ES. ES2
requires an unsized |
676 // format for glTexImage, unlike ES3 and desktop. | 652 // format for glTexImage, unlike ES3 and desktop. |
677 bool useSizedFormat = useTexStorage; | 653 bool useSizedFormat = useTexStorage; |
678 if (kGL_GrGLStandard == this->glStandard() || | 654 if (kGL_GrGLStandard == standard || |
679 (this->glVersion() >= GR_GL_VER(3, 0) && | 655 (version >= GR_GL_VER(3, 0) && |
680 // ES3 only works with sized BGRA8 format if "GL_APPLE_texture_format_B
GRA8888" enabled | 656 // ES3 only works with sized BGRA8 format if "GL_APPLE_texture_format_B
GRA8888" enabled |
681 (kBGRA_8888_GrPixelConfig != dataConfig || !this->glCaps().bgraIsIntern
alFormat()))) { | 657 (kBGRA_8888_GrPixelConfig != dataConfig || !caps.bgraIsInternalFormat()
))) { |
682 useSizedFormat = true; | 658 useSizedFormat = true; |
683 } | 659 } |
684 | 660 |
685 if (!this->configToGLFormats(dataConfig, useSizedFormat, &internalFormat, | 661 return useSizedFormat; |
686 &externalFormat, &externalType)) { | 662 } |
687 return false; | 663 |
688 } | 664 static void prepare_image_for_writing_to_texture(const GrSurfaceDesc& desc, cons
t GrGLCaps& caps, |
| 665 bool swFlipY, bool glFlipY, int
width, int height, |
| 666 int bpp, size_t rowBytes, const
void*& data, |
| 667 SkAutoSMalloc<128 * 128>& tempS
torage, |
| 668 const GrGLInterface* interface, |
| 669 bool& restoreGLRowLength) { |
| 670 if (NULL == interface) { |
| 671 return; |
| 672 } |
| 673 |
| 674 size_t trimRowBytes = width * bpp; |
689 | 675 |
690 /* | 676 /* |
691 * check whether to allocate a temporary buffer for flipping y or | 677 * check whether to allocate a temporary buffer for flipping y or |
692 * because our srcData has extra bytes past each row. If so, we need | 678 * because our srcData has extra bytes past each row. If so, we need |
693 * to trim those off here, since GL ES may not let us specify | 679 * to trim those off here, since GL ES may not let us specify |
694 * GL_UNPACK_ROW_LENGTH. | 680 * GL_UNPACK_ROW_LENGTH. |
695 */ | 681 */ |
696 bool restoreGLRowLength = false; | 682 restoreGLRowLength = false; |
| 683 |
| 684 if (caps.unpackRowLengthSupport() && !swFlipY) { |
| 685 // can't use this for flipping, only non-neg values allowed. :( |
| 686 if (rowBytes != trimRowBytes) { |
| 687 GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp); |
| 688 GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength
)); |
| 689 restoreGLRowLength = true; |
| 690 } |
| 691 } else { |
| 692 if (trimRowBytes != rowBytes || swFlipY) { |
| 693 // copy data into our new storage, skipping the trailing bytes |
| 694 size_t trimSize = height * trimRowBytes; |
| 695 const char* src = (const char*)data; |
| 696 if (swFlipY) { |
| 697 src += (height - 1) * rowBytes; |
| 698 } |
| 699 char* dst = (char*)tempStorage.reset(trimSize); |
| 700 for (int y = 0; y < height; y++) { |
| 701 memcpy(dst, src, trimRowBytes); |
| 702 if (swFlipY) { |
| 703 src -= rowBytes; |
| 704 } else { |
| 705 src += rowBytes; |
| 706 } |
| 707 dst += trimRowBytes; |
| 708 } |
| 709 // now point data to our copied version |
| 710 data = tempStorage.get(); |
| 711 } |
| 712 } |
| 713 if (glFlipY) { |
| 714 GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE)); |
| 715 } |
| 716 GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ALIGNMENT, |
| 717 static_cast<GrGLint>(GrUnpackAlignment(des
c.fConfig)))); |
| 718 } |
| 719 |
| 720 static void allocate_and_populate_uncompressed_texture(const GrGLInterface* inte
rface, |
| 721 bool useTexStorage, |
| 722 GrGLenum internalFormat, |
| 723 GrGLenum externalFormat, |
| 724 GrGLenum externalType, |
| 725 const GrSurfaceDesc& desc
, |
| 726 SkTArray<const void*>& da
ta, |
| 727 bool& succeeded) { |
| 728 CLEAR_ERROR_BEFORE_ALLOC(interface); |
| 729 if (useTexStorage) { |
| 730 // We never resize or change formats of textures. |
| 731 GL_ALLOC_CALL(interface, |
| 732 TexStorage2D(GR_GL_TEXTURE_2D, |
| 733 data.count(), |
| 734 internalFormat, |
| 735 desc.fWidth, desc.fHeight)); |
| 736 } else { |
| 737 int width = desc.fWidth; |
| 738 int height = desc.fHeight; |
| 739 for (int currentMipLevel = 0; currentMipLevel < data.count(); currentMip
Level++) { |
| 740 GL_ALLOC_CALL(interface, |
| 741 TexImage2D(GR_GL_TEXTURE_2D, |
| 742 currentMipLevel, |
| 743 internalFormat, |
| 744 width, height, |
| 745 0, // border |
| 746 externalFormat, externalType, |
| 747 data[currentMipLevel])); |
| 748 width /= 2; |
| 749 height /= 2; |
| 750 } |
| 751 } |
| 752 |
| 753 GrGLenum error = check_alloc_error(desc, interface); |
| 754 if (error != GR_GL_NO_ERROR) { |
| 755 succeeded = false; |
| 756 } else { |
| 757 int width = desc.fWidth; |
| 758 int height = desc.fHeight; |
| 759 for (int currentMipLevel = data.count(); currentMipLevel != 0; currentMi
pLevel--) { |
| 760 auto currentMipData = data[currentMipLevel]; |
| 761 GR_GL_CALL(interface, |
| 762 TexSubImage2D(GR_GL_TEXTURE_2D, |
| 763 currentMipLevel, |
| 764 0, // left |
| 765 0, // top |
| 766 width, height, |
| 767 externalFormat, externalType, |
| 768 currentMipData)); |
| 769 width /= 2; |
| 770 height /= 2; |
| 771 } |
| 772 } |
| 773 } |
| 774 |
| 775 static bool allocate_and_populate_compressed_texture(const GrGLInterface* interf
ace, |
| 776 bool useTexStorage, GrGLenu
m internalFormat, |
| 777 const GrSurfaceDesc& desc, |
| 778 SkTArray<const void*>& data
, |
| 779 size_t dataSize) { |
| 780 CLEAR_ERROR_BEFORE_ALLOC(interface); |
| 781 if (useTexStorage) { |
| 782 // We never resize or change formats of textures. |
| 783 GL_ALLOC_CALL(interface, |
| 784 TexStorage2D(GR_GL_TEXTURE_2D, |
| 785 data.count(), |
| 786 internalFormat, |
| 787 desc.fWidth, desc.fHeight)); |
| 788 } else { |
| 789 int width = desc.fWidth; |
| 790 int height = desc.fHeight; |
| 791 for (int currentMipLevel = 0; currentMipLevel < data.count(); currentMip
Level++) { |
| 792 GL_ALLOC_CALL(interface, |
| 793 CompressedTexImage2D(GR_GL_TEXTURE_2D, |
| 794 data.count(), |
| 795 internalFormat, |
| 796 width, height, |
| 797 0, // border |
| 798 SkToInt(dataSize), |
| 799 data[currentMipLevel])); |
| 800 width /= 2; |
| 801 height /= 2; |
| 802 } |
| 803 } |
| 804 |
| 805 GrGLenum error = check_alloc_error(desc, interface); |
| 806 if (error != GR_GL_NO_ERROR) { |
| 807 return false; |
| 808 } |
| 809 return true; |
| 810 } |
| 811 |
| 812 static void restore_gl_state(bool restoreGLRowLength, const GrGLInterface* inter
face, |
| 813 const GrGLCaps& caps, bool glFlipY) { |
| 814 if (restoreGLRowLength) { |
| 815 SkASSERT(caps.unpackRowLengthSupport()); |
| 816 GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0)); |
| 817 } |
| 818 if (glFlipY) { |
| 819 GR_GL_CALL(interface, PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE)); |
| 820 } |
| 821 } |
| 822 |
| 823 bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc, |
| 824 bool isNewTexture, |
| 825 int left, int top, int width, int height, |
| 826 GrPixelConfig dataConfig, |
| 827 const void* data, |
| 828 size_t rowBytes) { |
| 829 SkASSERT(data || isNewTexture); |
| 830 |
| 831 // If we're uploading compressed data then we should be using uploadCompress
edTexData |
| 832 SkASSERT(!GrPixelConfigIsCompressed(dataConfig)); |
| 833 |
| 834 size_t bpp = GrBytesPerPixel(dataConfig); |
| 835 if (!adjust_pixel_ops_params(desc.fWidth, desc.fHeight, bpp, &left, &top, |
| 836 &width, &height, &data, &rowBytes)) { |
| 837 return false; |
| 838 } |
| 839 |
| 840 bool useTexStorage = can_use_tex_storage(this->glCaps(), this->glStandard(), |
| 841 desc); |
| 842 bool useSizedFormat = can_use_sized_format(useTexStorage, this->glCaps(), th
is->glStandard(), |
| 843 this->glVersion(), dataConfig); |
| 844 |
| 845 GrGLenum internalFormat = 0x0; // suppress warning |
| 846 GrGLenum externalFormat = 0x0; // suppress warning |
| 847 GrGLenum externalType = 0x0; // suppress warning |
| 848 |
| 849 if (!this->configToGLFormats(dataConfig, useSizedFormat, &internalFormat, |
| 850 &externalFormat, &externalType)) { |
| 851 return false; |
| 852 } |
| 853 |
697 bool swFlipY = false; | 854 bool swFlipY = false; |
698 bool glFlipY = false; | 855 bool glFlipY = false; |
| 856 |
| 857 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { |
| 858 if (glCaps().unpackFlipYSupport()) { |
| 859 glFlipY = true; |
| 860 } else { |
| 861 swFlipY = true; |
| 862 } |
| 863 } |
| 864 |
| 865 bool restoreGLRowLength = false; |
| 866 |
| 867 // in case we need a temporary, trimmed copy of the src pixels |
| 868 SkAutoSMalloc<128 * 128> tempStorage; |
699 if (data) { | 869 if (data) { |
700 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { | 870 prepare_image_for_writing_to_texture(desc, this->glCaps(), swFlipY, glFl
ipY, width, height, |
701 if (this->glCaps().unpackFlipYSupport()) { | 871 bpp, rowBytes, data, tempStorage, t
his->glInterface(), |
702 glFlipY = true; | 872 restoreGLRowLength); |
703 } else { | |
704 swFlipY = true; | |
705 } | |
706 } | |
707 if (this->glCaps().unpackRowLengthSupport() && !swFlipY) { | |
708 // can't use this for flipping, only non-neg values allowed. :( | |
709 if (rowBytes != trimRowBytes) { | |
710 GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp); | |
711 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength)); | |
712 restoreGLRowLength = true; | |
713 } | |
714 } else { | |
715 if (trimRowBytes != rowBytes || swFlipY) { | |
716 // copy data into our new storage, skipping the trailing bytes | |
717 size_t trimSize = height * trimRowBytes; | |
718 const char* src = (const char*)data; | |
719 if (swFlipY) { | |
720 src += (height - 1) * rowBytes; | |
721 } | |
722 char* dst = (char*)tempStorage.reset(trimSize); | |
723 for (int y = 0; y < height; y++) { | |
724 memcpy(dst, src, trimRowBytes); | |
725 if (swFlipY) { | |
726 src -= rowBytes; | |
727 } else { | |
728 src += rowBytes; | |
729 } | |
730 dst += trimRowBytes; | |
731 } | |
732 // now point data to our copied version | |
733 data = tempStorage.get(); | |
734 } | |
735 } | |
736 if (glFlipY) { | |
737 GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE)); | |
738 } | |
739 GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, | |
740 static_cast<GrGLint>(GrUnpackAlignment(dataConfig)))); | |
741 } | 873 } |
742 bool succeeded = true; | 874 bool succeeded = true; |
743 if (isNewTexture && | 875 if (isNewTexture && |
744 0 == left && 0 == top && | 876 0 == left && 0 == top && |
745 desc.fWidth == width && desc.fHeight == height) { | 877 desc.fWidth == width && desc.fHeight == height) { |
746 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); | 878 const int mipLevelCount = 1; |
747 if (useTexStorage) { | 879 SkTArray<const void*> mipLevels(mipLevelCount); |
748 // We never resize or change formats of textures. | 880 mipLevels[0] = data; |
749 GL_ALLOC_CALL(this->glInterface(), | 881 allocate_and_populate_uncompressed_texture(this->glInterface(), useTexSt
orage, |
750 TexStorage2D(GR_GL_TEXTURE_2D, | 882 internalFormat, externalForma
t, externalType, |
751 1, // levels | 883 desc, mipLevels, succeeded); |
752 internalFormat, | |
753 desc.fWidth, desc.fHeight)); | |
754 } else { | |
755 GL_ALLOC_CALL(this->glInterface(), | |
756 TexImage2D(GR_GL_TEXTURE_2D, | |
757 0, // level | |
758 internalFormat, | |
759 desc.fWidth, desc.fHeight, | |
760 0, // border | |
761 externalFormat, externalType, | |
762 data)); | |
763 } | |
764 GrGLenum error = check_alloc_error(desc, this->glInterface()); | |
765 if (error != GR_GL_NO_ERROR) { | |
766 succeeded = false; | |
767 } else { | |
768 // if we have data and we used TexStorage to create the texture, we | |
769 // now upload with TexSubImage. | |
770 if (data && useTexStorage) { | |
771 GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, | |
772 0, // level | |
773 left, top, | |
774 width, height, | |
775 externalFormat, externalType, | |
776 data)); | |
777 } | |
778 } | |
779 } else { | 884 } else { |
780 if (swFlipY || glFlipY) { | 885 if (swFlipY || glFlipY) { |
781 top = desc.fHeight - (top + height); | 886 top = desc.fHeight - (top + height); |
782 } | 887 } |
783 GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, | 888 GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, |
784 0, // level | 889 0, // level |
785 left, top, | 890 left, top, |
786 width, height, | 891 width, height, |
787 externalFormat, externalType, data)); | 892 externalFormat, externalType, data)); |
788 } | 893 } |
789 | 894 |
790 if (restoreGLRowLength) { | 895 restore_gl_state(restoreGLRowLength, this->glInterface(), this->glCaps(), gl
FlipY); |
791 SkASSERT(this->glCaps().unpackRowLengthSupport()); | 896 |
792 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0)); | |
793 } | |
794 if (glFlipY) { | |
795 GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE)); | |
796 } | |
797 return succeeded; | 897 return succeeded; |
798 } | 898 } |
799 | 899 |
800 // TODO: This function is using a lot of wonky semantics like, if width == -1 | 900 // TODO: This function is using a lot of wonky semantics like, if width == -1 |
801 // then set width = desc.fWdith ... blah. A better way to do it might be to | 901 // then set width = desc.fWdith ... blah. A better way to do it might be to |
802 // create a CompressedTexData struct that takes a desc/ptr and figures out | 902 // create a CompressedTexData struct that takes a desc/ptr and figures out |
803 // the proper upload semantics. Then users can construct this function how they | 903 // the proper upload semantics. Then users can construct this function how they |
804 // see fit if they want to go against the "standard" way to do it. | 904 // see fit if they want to go against the "standard" way to do it. |
805 bool GrGLGpu::uploadCompressedTexData(const GrSurfaceDesc& desc, | 905 bool GrGLGpu::uploadCompressedTexData(const GrSurfaceDesc& desc, |
806 const void* data, | 906 const void* data, |
(...skipping 15 matching lines...) Expand all Loading... |
822 | 922 |
823 if (-1 == height) { | 923 if (-1 == height) { |
824 height = desc.fHeight; | 924 height = desc.fHeight; |
825 } | 925 } |
826 #ifdef SK_DEBUG | 926 #ifdef SK_DEBUG |
827 else { | 927 else { |
828 SkASSERT(height <= desc.fHeight); | 928 SkASSERT(height <= desc.fHeight); |
829 } | 929 } |
830 #endif | 930 #endif |
831 | 931 |
| 932 bool useTexStorage = can_use_tex_storage(this->glCaps(), this->glStandard(), |
| 933 desc); |
| 934 |
832 // Make sure that the width and height that we pass to OpenGL | 935 // Make sure that the width and height that we pass to OpenGL |
833 // is a multiple of the block size. | 936 // is a multiple of the block size. |
834 size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, width, height); | 937 size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, width, height); |
835 | 938 |
836 // We only need the internal format for compressed 2D textures. | 939 // We only need the internal format for compressed 2D textures. |
837 GrGLenum internalFormat = 0; | 940 GrGLenum internalFormat = 0; |
838 if (!this->configToGLFormats(desc.fConfig, false, &internalFormat, NULL, NUL
L)) { | 941 if (!this->configToGLFormats(desc.fConfig, false, &internalFormat, NULL, NUL
L)) { |
839 return false; | 942 return false; |
840 } | 943 } |
841 | 944 |
842 if (isNewTexture) { | 945 if (isNewTexture) { |
843 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); | 946 const int mipLevelCount = 1; |
844 GL_ALLOC_CALL(this->glInterface(), | 947 SkTArray<const void*> mipLevels(mipLevelCount); |
845 CompressedTexImage2D(GR_GL_TEXTURE_2D, | 948 mipLevels[0] = data; |
846 0, // level | 949 return allocate_and_populate_compressed_texture(this->glInterface(), use
TexStorage, |
847 internalFormat, | 950 internalFormat, desc, mi
pLevels, dataSize); |
848 width, height, | |
849 0, // border | |
850 SkToInt(dataSize), | |
851 data)); | |
852 GrGLenum error = check_alloc_error(desc, this->glInterface()); | |
853 if (error != GR_GL_NO_ERROR) { | |
854 return false; | |
855 } | |
856 } else { | 951 } else { |
857 // Paletted textures can't be updated. | 952 // Paletted textures can't be updated. |
858 if (GR_GL_PALETTE8_RGBA8 == internalFormat) { | 953 if (GR_GL_PALETTE8_RGBA8 == internalFormat) { |
859 return false; | 954 return false; |
860 } | 955 } |
861 GL_CALL(CompressedTexSubImage2D(GR_GL_TEXTURE_2D, | 956 GL_CALL(CompressedTexSubImage2D(GR_GL_TEXTURE_2D, |
862 0, // level | 957 0, // level |
863 left, top, | 958 left, top, |
864 width, height, | 959 width, height, |
865 internalFormat, | 960 internalFormat, |
866 SkToInt(dataSize), | 961 SkToInt(dataSize), |
867 data)); | 962 data)); |
868 } | 963 } |
869 | 964 |
870 return true; | 965 return true; |
871 } | 966 } |
872 | 967 |
| 968 bool GrGLGpu::uploadMipmappedTexData(const GrSurfaceDesc& desc, |
| 969 const SkMipMap& data) { |
| 970 // If we're uploading compressed data then we should be using uploadCompress
edMipmappedTexData |
| 971 SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig)); |
| 972 |
| 973 size_t bpp = GrBytesPerPixel(desc.fConfig); |
| 974 |
| 975 bool useTexStorage = can_use_tex_storage(this->glCaps(), this->glStandard(), |
| 976 desc); |
| 977 bool useSizedFormat = can_use_sized_format(useTexStorage, this->glCaps(), th
is->glStandard(), |
| 978 this->glVersion(), desc.fConfig); |
| 979 |
| 980 GrGLenum internalFormat = 0x0; // suppress warning |
| 981 GrGLenum externalFormat = 0x0; // suppress warning |
| 982 GrGLenum externalType = 0x0; // suppress warning |
| 983 |
| 984 if (!this->configToGLFormats(desc.fConfig, useSizedFormat, &internalFormat, |
| 985 &externalFormat, &externalType)) { |
| 986 return false; |
| 987 } |
| 988 |
| 989 bool swFlipY = false; |
| 990 bool glFlipY = false; |
| 991 |
| 992 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { |
| 993 if (glCaps().unpackFlipYSupport()) { |
| 994 glFlipY = true; |
| 995 } else { |
| 996 swFlipY = true; |
| 997 } |
| 998 } |
| 999 |
| 1000 bool restoreGLRowLength = false; |
| 1001 |
| 1002 // in case we need a temporary, trimmed copy of the src pixels |
| 1003 SkAutoSMalloc<128 * 128> tempStorage; |
| 1004 |
| 1005 bool succeeded = true; |
| 1006 auto mipLevelCount = data.getLevelsCount(); |
| 1007 SkTArray<const void*> mipLevels(mipLevelCount); |
| 1008 for (int currentMipLevel = mipLevelCount; currentMipLevel != 0; currentMipLe
vel--) { |
| 1009 SkMipMap::Level currentMipData; |
| 1010 if (data.getLevel(currentMipLevel, ¤tMipData)) { |
| 1011 mipLevels[currentMipLevel] = currentMipData.fPixels; |
| 1012 |
| 1013 prepare_image_for_writing_to_texture(desc, this->glCaps(), swFlipY,
glFlipY, |
| 1014 currentMipData.fWidth, currentM
ipData.fHeight, |
| 1015 bpp, currentMipData.fRowBytes, |
| 1016 mipLevels[currentMipLevel], tem
pStorage, |
| 1017 this->glInterface(), restoreGLR
owLength); |
| 1018 } |
| 1019 } |
| 1020 allocate_and_populate_uncompressed_texture(this->glInterface(), useTexStorag
e, internalFormat, |
| 1021 externalFormat, externalType, des
c, mipLevels, |
| 1022 succeeded); |
| 1023 |
| 1024 restore_gl_state(restoreGLRowLength, this->glInterface(), this->glCaps(), gl
FlipY); |
| 1025 |
| 1026 return succeeded; |
| 1027 } |
| 1028 |
| 1029 bool GrGLGpu::uploadCompressedMipmappedTexData(const GrSurfaceDesc& desc, |
| 1030 const SkMipMap& data) { |
| 1031 // No support for software flip y, yet... |
| 1032 SkASSERT(kBottomLeft_GrSurfaceOrigin != desc.fOrigin); |
| 1033 |
| 1034 // Make sure that the width and height that we pass to OpenGL |
| 1035 // is a multiple of the block size. |
| 1036 size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, desc.fWidth, desc
.fHeight); |
| 1037 |
| 1038 bool useTexStorage = can_use_tex_storage(this->glCaps(), this->glStandard(), |
| 1039 desc); |
| 1040 bool useSizedFormat = can_use_sized_format(useTexStorage, this->glCaps(), th
is->glStandard(), |
| 1041 this->glVersion(), desc.fConfig); |
| 1042 |
| 1043 // We only need the internal format for compressed 2D textures. |
| 1044 GrGLenum internalFormat = 0; |
| 1045 if (!this->configToGLFormats(desc.fConfig, false, &internalFormat, NULL, NUL
L)) { |
| 1046 return false; |
| 1047 } |
| 1048 |
| 1049 auto mipLevelCount = data.getLevelsCount(); |
| 1050 SkTArray<const void*> mipLevels(mipLevelCount); |
| 1051 for (int currentLevelIndex = mipLevelCount; currentLevelIndex != 0; currentL
evelIndex--) { |
| 1052 SkMipMap::Level currentLevel; |
| 1053 if (data.getLevel(currentLevelIndex, ¤tLevel)) { |
| 1054 mipLevels[currentLevelIndex] = currentLevel.fPixels; |
| 1055 } |
| 1056 } |
| 1057 return allocate_and_populate_compressed_texture(this->glInterface(), useTexS
torage, |
| 1058 internalFormat, desc, mipLev
els, dataSize); |
| 1059 } |
| 1060 |
873 static bool renderbuffer_storage_msaa(const GrGLContext& ctx, | 1061 static bool renderbuffer_storage_msaa(const GrGLContext& ctx, |
874 int sampleCount, | 1062 int sampleCount, |
875 GrGLenum format, | 1063 GrGLenum format, |
876 int width, int height) { | 1064 int width, int height) { |
877 CLEAR_ERROR_BEFORE_ALLOC(ctx.interface()); | 1065 CLEAR_ERROR_BEFORE_ALLOC(ctx.interface()); |
878 SkASSERT(GrGLCaps::kNone_MSFBOType != ctx.caps()->msFBOType()); | 1066 SkASSERT(GrGLCaps::kNone_MSFBOType != ctx.caps()->msFBOType()); |
879 switch (ctx.caps()->msFBOType()) { | 1067 switch (ctx.caps()->msFBOType()) { |
880 case GrGLCaps::kDesktop_ARB_MSFBOType: | 1068 case GrGLCaps::kDesktop_ARB_MSFBOType: |
881 case GrGLCaps::kDesktop_EXT_MSFBOType: | 1069 case GrGLCaps::kDesktop_EXT_MSFBOType: |
882 case GrGLCaps::kMixedSamples_MSFBOType: | 1070 case GrGLCaps::kMixedSamples_MSFBOType: |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1025 // SkDEBUGFAIL("null texture"); | 1213 // SkDEBUGFAIL("null texture"); |
1026 return NULL; | 1214 return NULL; |
1027 } | 1215 } |
1028 | 1216 |
1029 #if 0 && defined(SK_DEBUG) | 1217 #if 0 && defined(SK_DEBUG) |
1030 static size_t as_size_t(int x) { | 1218 static size_t as_size_t(int x) { |
1031 return x; | 1219 return x; |
1032 } | 1220 } |
1033 #endif | 1221 #endif |
1034 | 1222 |
| 1223 static GrGLTexture::IDDesc generate_and_bind_gl_texture(const GrGLInterface* int
erface, |
| 1224 GrGpuResource::LifeCycle
lifeCycle) { |
| 1225 GrGLTexture::IDDesc idDesc; |
| 1226 GR_GL_CALL(interface, GenTextures(1, &idDesc.fTextureID)); |
| 1227 idDesc.fLifeCycle = lifeCycle; |
| 1228 return idDesc; |
| 1229 } |
| 1230 |
| 1231 static GrGLTexture::TexParams set_initial_texture_params(const GrGLInterface* in
terface) { |
| 1232 // Some drivers like to know filter/wrap before seeing glTexImage2D. Some |
| 1233 // drivers have a bug where an FBO won't be complete if it includes a |
| 1234 // texture that is not mipmap complete (considering the filter in use). |
| 1235 GrGLTexture::TexParams initialTexParams; |
| 1236 // we only set a subset here so invalidate first |
| 1237 initialTexParams.invalidate(); |
| 1238 initialTexParams.fMinFilter = GR_GL_NEAREST; |
| 1239 initialTexParams.fMagFilter = GR_GL_NEAREST; |
| 1240 initialTexParams.fWrapS = GR_GL_CLAMP_TO_EDGE; |
| 1241 initialTexParams.fWrapT = GR_GL_CLAMP_TO_EDGE; |
| 1242 GR_GL_CALL(interface, TexParameteri(GR_GL_TEXTURE_2D, |
| 1243 GR_GL_TEXTURE_MAG_FILTER, |
| 1244 initialTexParams.fMagFilter)); |
| 1245 GR_GL_CALL(interface, TexParameteri(GR_GL_TEXTURE_2D, |
| 1246 GR_GL_TEXTURE_MIN_FILTER, |
| 1247 initialTexParams.fMinFilter)); |
| 1248 GR_GL_CALL(interface, TexParameteri(GR_GL_TEXTURE_2D, |
| 1249 GR_GL_TEXTURE_WRAP_S, |
| 1250 initialTexParams.fWrapS)); |
| 1251 GR_GL_CALL(interface, TexParameteri(GR_GL_TEXTURE_2D, |
| 1252 GR_GL_TEXTURE_WRAP_T, |
| 1253 initialTexParams.fWrapT)); |
| 1254 return initialTexParams; |
| 1255 } |
| 1256 |
1035 GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc, | 1257 GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc, |
1036 GrGpuResource::LifeCycle lifeCycle, | 1258 GrGpuResource::LifeCycle lifeCycle, |
1037 const void* srcData, size_t rowBytes) { | 1259 const void* srcData, size_t rowBytes) { |
1038 // We fail if the MSAA was requested and is not available. | 1260 // We fail if the MSAA was requested and is not available. |
1039 if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleC
nt) { | 1261 if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleC
nt) { |
1040 //SkDebugf("MSAA RT requested but not supported on this platform."); | 1262 //SkDebugf("MSAA RT requested but not supported on this platform."); |
1041 return return_null_texture(); | 1263 return return_null_texture(); |
1042 } | 1264 } |
1043 | 1265 |
1044 bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag); | 1266 bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag); |
1045 | 1267 |
1046 GrGLTexture::IDDesc idDesc; | 1268 auto idDesc = generate_and_bind_gl_texture(this->glInterface(), lifeCycle); |
1047 GL_CALL(GenTextures(1, &idDesc.fTextureID)); | |
1048 idDesc.fLifeCycle = lifeCycle; | |
1049 | |
1050 if (!idDesc.fTextureID) { | 1269 if (!idDesc.fTextureID) { |
1051 return return_null_texture(); | 1270 return return_null_texture(); |
1052 } | 1271 } |
1053 | 1272 |
1054 this->setScratchTextureUnit(); | 1273 this->setScratchTextureUnit(); |
1055 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, idDesc.fTextureID)); | 1274 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, idDesc.fTextureID)); |
1056 | 1275 |
1057 if (renderTarget && this->glCaps().textureUsageSupport()) { | 1276 if (renderTarget && this->glCaps().textureUsageSupport()) { |
1058 // provides a hint about how this texture will be used | 1277 // provides a hint about how this texture will be used |
1059 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, | 1278 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, |
1060 GR_GL_TEXTURE_USAGE, | 1279 GR_GL_TEXTURE_USAGE, |
1061 GR_GL_FRAMEBUFFER_ATTACHMENT)); | 1280 GR_GL_FRAMEBUFFER_ATTACHMENT)); |
1062 } | 1281 } |
1063 | 1282 |
1064 // Some drivers like to know filter/wrap before seeing glTexImage2D. Some | 1283 auto initialTexParams = set_initial_texture_params(this->glInterface()); |
1065 // drivers have a bug where an FBO won't be complete if it includes a | 1284 |
1066 // texture that is not mipmap complete (considering the filter in use). | |
1067 GrGLTexture::TexParams initialTexParams; | |
1068 // we only set a subset here so invalidate first | |
1069 initialTexParams.invalidate(); | |
1070 initialTexParams.fMinFilter = GR_GL_NEAREST; | |
1071 initialTexParams.fMagFilter = GR_GL_NEAREST; | |
1072 initialTexParams.fWrapS = GR_GL_CLAMP_TO_EDGE; | |
1073 initialTexParams.fWrapT = GR_GL_CLAMP_TO_EDGE; | |
1074 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, | |
1075 GR_GL_TEXTURE_MAG_FILTER, | |
1076 initialTexParams.fMagFilter)); | |
1077 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, | |
1078 GR_GL_TEXTURE_MIN_FILTER, | |
1079 initialTexParams.fMinFilter)); | |
1080 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, | |
1081 GR_GL_TEXTURE_WRAP_S, | |
1082 initialTexParams.fWrapS)); | |
1083 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, | |
1084 GR_GL_TEXTURE_WRAP_T, | |
1085 initialTexParams.fWrapT)); | |
1086 if (!this->uploadTexData(desc, true, 0, 0, | 1285 if (!this->uploadTexData(desc, true, 0, 0, |
1087 desc.fWidth, desc.fHeight, | 1286 desc.fWidth, desc.fHeight, |
1088 desc.fConfig, srcData, rowBytes)) { | 1287 desc.fConfig, srcData, rowBytes)) { |
1089 GL_CALL(DeleteTextures(1, &idDesc.fTextureID)); | 1288 GL_CALL(DeleteTextures(1, &idDesc.fTextureID)); |
1090 return return_null_texture(); | 1289 return return_null_texture(); |
1091 } | 1290 } |
1092 | 1291 |
1093 GrGLTexture* tex; | 1292 GrGLTexture* tex; |
1094 if (renderTarget) { | 1293 if (renderTarget) { |
1095 // unbind the texture from the texture unit before binding it to the fra
me buffer | 1294 // unbind the texture from the texture unit before binding it to the fra
me buffer |
(...skipping 17 matching lines...) Expand all Loading... |
1113 } | 1312 } |
1114 | 1313 |
1115 GrTexture* GrGLGpu::onCreateCompressedTexture(const GrSurfaceDesc& desc, | 1314 GrTexture* GrGLGpu::onCreateCompressedTexture(const GrSurfaceDesc& desc, |
1116 GrGpuResource::LifeCycle lifeCycle
, | 1315 GrGpuResource::LifeCycle lifeCycle
, |
1117 const void* srcData) { | 1316 const void* srcData) { |
1118 // Make sure that we're not flipping Y. | 1317 // Make sure that we're not flipping Y. |
1119 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { | 1318 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { |
1120 return return_null_texture(); | 1319 return return_null_texture(); |
1121 } | 1320 } |
1122 | 1321 |
1123 GrGLTexture::IDDesc idDesc; | 1322 auto idDesc = generate_and_bind_gl_texture(this->glInterface(), lifeCycle); |
1124 GL_CALL(GenTextures(1, &idDesc.fTextureID)); | |
1125 idDesc.fLifeCycle = lifeCycle; | |
1126 | |
1127 if (!idDesc.fTextureID) { | 1323 if (!idDesc.fTextureID) { |
1128 return return_null_texture(); | 1324 return return_null_texture(); |
1129 } | 1325 } |
1130 | 1326 |
1131 this->setScratchTextureUnit(); | 1327 this->setScratchTextureUnit(); |
1132 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, idDesc.fTextureID)); | 1328 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, idDesc.fTextureID)); |
1133 | 1329 |
1134 // Some drivers like to know filter/wrap before seeing glTexImage2D. Some | 1330 auto initialTexParams = set_initial_texture_params(this->glInterface()); |
1135 // drivers have a bug where an FBO won't be complete if it includes a | |
1136 // texture that is not mipmap complete (considering the filter in use). | |
1137 GrGLTexture::TexParams initialTexParams; | |
1138 // we only set a subset here so invalidate first | |
1139 initialTexParams.invalidate(); | |
1140 initialTexParams.fMinFilter = GR_GL_NEAREST; | |
1141 initialTexParams.fMagFilter = GR_GL_NEAREST; | |
1142 initialTexParams.fWrapS = GR_GL_CLAMP_TO_EDGE; | |
1143 initialTexParams.fWrapT = GR_GL_CLAMP_TO_EDGE; | |
1144 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, | |
1145 GR_GL_TEXTURE_MAG_FILTER, | |
1146 initialTexParams.fMagFilter)); | |
1147 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, | |
1148 GR_GL_TEXTURE_MIN_FILTER, | |
1149 initialTexParams.fMinFilter)); | |
1150 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, | |
1151 GR_GL_TEXTURE_WRAP_S, | |
1152 initialTexParams.fWrapS)); | |
1153 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, | |
1154 GR_GL_TEXTURE_WRAP_T, | |
1155 initialTexParams.fWrapT)); | |
1156 | 1331 |
1157 if (!this->uploadCompressedTexData(desc, srcData)) { | 1332 if (!this->uploadCompressedTexData(desc, srcData)) { |
1158 GL_CALL(DeleteTextures(1, &idDesc.fTextureID)); | 1333 GL_CALL(DeleteTextures(1, &idDesc.fTextureID)); |
1159 return return_null_texture(); | 1334 return return_null_texture(); |
1160 } | 1335 } |
1161 | 1336 |
1162 GrGLTexture* tex; | 1337 GrGLTexture* tex; |
1163 tex = SkNEW_ARGS(GrGLTexture, (this, desc, idDesc)); | 1338 tex = SkNEW_ARGS(GrGLTexture, (this, desc, idDesc)); |
1164 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); | 1339 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); |
1165 #ifdef TRACE_TEXTURE_CREATION | 1340 #ifdef TRACE_TEXTURE_CREATION |
1166 SkDebugf("--- new compressed texture [%d] size=(%d %d) config=%d\n", | 1341 SkDebugf("--- new compressed texture [%d] size=(%d %d) config=%d\n", |
1167 glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig); | 1342 glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig); |
1168 #endif | 1343 #endif |
1169 return tex; | 1344 return tex; |
1170 } | 1345 } |
1171 | 1346 |
| 1347 GrTexture* GrGLGpu::onCreateMipmappedTexture(const GrSurfaceDesc& desc, |
| 1348 GrGpuResource::LifeCycle lifeCycle, |
| 1349 const SkMipMap& srcData) |
| 1350 { |
| 1351 // We fail if the MSAA was requested and is not available. |
| 1352 if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleC
nt) { |
| 1353 //SkDebugf("MSAA RT requested but not supported on this platform."); |
| 1354 return return_null_texture(); |
| 1355 } |
| 1356 |
| 1357 bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag); |
| 1358 |
| 1359 auto idDesc = generate_and_bind_gl_texture(this->glInterface(), lifeCycle); |
| 1360 if (!idDesc.fTextureID) { |
| 1361 return return_null_texture(); |
| 1362 } |
| 1363 |
| 1364 if (renderTarget && this->glCaps().textureUsageSupport()) { |
| 1365 // provides a hint about how this texture will be used |
| 1366 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, |
| 1367 GR_GL_TEXTURE_USAGE, |
| 1368 GR_GL_FRAMEBUFFER_ATTACHMENT)); |
| 1369 } |
| 1370 |
| 1371 auto initialTexParams = set_initial_texture_params(this->glInterface()); |
| 1372 |
| 1373 if (!this->uploadMipmappedTexData(desc, srcData)) { |
| 1374 GL_CALL(DeleteTextures(1, &idDesc.fTextureID)); |
| 1375 return return_null_texture(); |
| 1376 } |
| 1377 |
| 1378 GrGLTexture* tex; |
| 1379 if (renderTarget) { |
| 1380 // unbind the texture from the texture unit before binding it to the fra
me buffer |
| 1381 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, 0)); |
| 1382 GrGLRenderTarget::IDDesc rtIDDesc; |
| 1383 |
| 1384 if (!this->createRenderTargetObjects(desc, lifeCycle, idDesc.fTextureID,
&rtIDDesc)) { |
| 1385 GL_CALL(DeleteTextures(1, &idDesc.fTextureID)); |
| 1386 return return_null_texture(); |
| 1387 } |
| 1388 tex = SkNEW_ARGS(GrGLTextureRenderTarget, (this, desc, idDesc, rtIDDesc)
); |
| 1389 } else { |
| 1390 tex = SkNEW_ARGS(GrGLTexture, (this, desc, idDesc)); |
| 1391 } |
| 1392 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); |
| 1393 #ifdef TRACE_TEXTURE_CREATION |
| 1394 SkDebugf("--- new mipmapped texture [%d] size=(%d %d) config=%d\n", |
| 1395 glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig); |
| 1396 #endif |
| 1397 return tex; |
| 1398 } |
| 1399 |
| 1400 GrTexture* GrGLGpu::onCreateCompressedMipmappedTexture(const GrSurfaceDesc& desc
, |
| 1401 GrGpuResource::LifeCycle
lifeCycle, |
| 1402 const SkMipMap& srcData) |
| 1403 { |
| 1404 // Make sure that we're not flipping Y. |
| 1405 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { |
| 1406 return return_null_texture(); |
| 1407 } |
| 1408 |
| 1409 auto idDesc = generate_and_bind_gl_texture(this->glInterface(), lifeCycle); |
| 1410 if (!idDesc.fTextureID) { |
| 1411 return return_null_texture(); |
| 1412 } |
| 1413 |
| 1414 this->setScratchTextureUnit(); |
| 1415 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, idDesc.fTextureID)); |
| 1416 |
| 1417 auto initialTexParams = set_initial_texture_params(this->glInterface()); |
| 1418 |
| 1419 if (!this->uploadCompressedMipmappedTexData(desc, srcData)) { |
| 1420 GL_CALL(DeleteTextures(1, &idDesc.fTextureID)); |
| 1421 return return_null_texture(); |
| 1422 } |
| 1423 |
| 1424 GrGLTexture* tex; |
| 1425 tex = SkNEW_ARGS(GrGLTexture, (this, desc, idDesc)); |
| 1426 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); |
| 1427 #ifdef TRACE_TEXTURE_CREATION |
| 1428 SkDebugf("--- new compressed mipmapped texture [%d] size=(%d %d) config=%d\n
", |
| 1429 glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig); |
| 1430 #endif |
| 1431 return tex; |
| 1432 } |
| 1433 |
1172 namespace { | 1434 namespace { |
1173 | 1435 |
1174 const GrGLuint kUnknownBitCount = GrGLStencilAttachment::kUnknownBitCount; | 1436 const GrGLuint kUnknownBitCount = GrGLStencilAttachment::kUnknownBitCount; |
1175 | 1437 |
1176 void inline get_stencil_rb_sizes(const GrGLInterface* gl, | 1438 void inline get_stencil_rb_sizes(const GrGLInterface* gl, |
1177 GrGLStencilAttachment::Format* format) { | 1439 GrGLStencilAttachment::Format* format) { |
1178 | 1440 |
1179 // we shouldn't ever know one size and not the other | 1441 // we shouldn't ever know one size and not the other |
1180 SkASSERT((kUnknownBitCount == format->fStencilBits) == | 1442 SkASSERT((kUnknownBitCount == format->fStencilBits) == |
1181 (kUnknownBitCount == format->fTotalBits)); | 1443 (kUnknownBitCount == format->fTotalBits)); |
(...skipping 1974 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3156 this->setVertexArrayID(gpu, 0); | 3418 this->setVertexArrayID(gpu, 0); |
3157 } | 3419 } |
3158 int attrCount = gpu->glCaps().maxVertexAttributes(); | 3420 int attrCount = gpu->glCaps().maxVertexAttributes(); |
3159 if (fDefaultVertexArrayAttribState.count() != attrCount) { | 3421 if (fDefaultVertexArrayAttribState.count() != attrCount) { |
3160 fDefaultVertexArrayAttribState.resize(attrCount); | 3422 fDefaultVertexArrayAttribState.resize(attrCount); |
3161 } | 3423 } |
3162 attribState = &fDefaultVertexArrayAttribState; | 3424 attribState = &fDefaultVertexArrayAttribState; |
3163 } | 3425 } |
3164 return attribState; | 3426 return attribState; |
3165 } | 3427 } |
OLD | NEW |