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

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

Issue 1249543003: Creating functions for uploading a mipmapped texture. (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: Refactoring the mipmap level count out. Cleaning includes. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 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
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
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
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 &currentMipWidth,
879 &currentMipHeight,
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
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
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
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
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
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
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
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 }
OLDNEW
« src/core/SkMipMap.h ('K') | « src/gpu/gl/GrGLGpu.h ('k') | src/gpu/gl/GrGLTexture.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698