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 <algorithm> | |
10 #include <limits> | |
11 | |
9 #include "GrGLGpu.h" | 12 #include "GrGLGpu.h" |
10 #include "GrGLGLSL.h" | 13 #include "GrGLGLSL.h" |
11 #include "GrGLStencilAttachment.h" | 14 #include "GrGLStencilAttachment.h" |
12 #include "GrGLTextureRenderTarget.h" | 15 #include "GrGLTextureRenderTarget.h" |
13 #include "GrGpuResourcePriv.h" | 16 #include "GrGpuResourcePriv.h" |
14 #include "GrPipeline.h" | 17 #include "GrPipeline.h" |
15 #include "GrRenderTargetPriv.h" | 18 #include "GrRenderTargetPriv.h" |
16 #include "GrSurfacePriv.h" | 19 #include "GrSurfacePriv.h" |
17 #include "GrTexturePriv.h" | 20 #include "GrTexturePriv.h" |
18 #include "GrTypes.h" | 21 #include "GrTypes.h" |
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
419 | 422 |
420 int maxSize = this->caps()->maxTextureSize(); | 423 int maxSize = this->caps()->maxTextureSize(); |
421 if (desc.fWidth > maxSize || desc.fHeight > maxSize) { | 424 if (desc.fWidth > maxSize || desc.fHeight > maxSize) { |
422 return nullptr; | 425 return nullptr; |
423 } | 426 } |
424 | 427 |
425 GrGLTexture::IDDesc idDesc; | 428 GrGLTexture::IDDesc idDesc; |
426 GrSurfaceDesc surfDesc; | 429 GrSurfaceDesc surfDesc; |
427 | 430 |
428 idDesc.fTextureID = static_cast<GrGLuint>(desc.fTextureHandle); | 431 idDesc.fTextureID = static_cast<GrGLuint>(desc.fTextureHandle); |
429 | 432 |
430 switch (ownership) { | 433 switch (ownership) { |
431 case kAdopt_GrWrapOwnership: | 434 case kAdopt_GrWrapOwnership: |
432 idDesc.fLifeCycle = GrGpuResource::kAdopted_LifeCycle; | 435 idDesc.fLifeCycle = GrGpuResource::kAdopted_LifeCycle; |
433 break; | 436 break; |
434 case kBorrow_GrWrapOwnership: | 437 case kBorrow_GrWrapOwnership: |
435 idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle; | 438 idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle; |
436 break; | 439 break; |
437 } | 440 } |
438 | 441 |
439 // next line relies on GrBackendTextureDesc's flags matching GrTexture's | 442 // next line relies on GrBackendTextureDesc's flags matching GrTexture's |
440 surfDesc.fFlags = (GrSurfaceFlags) desc.fFlags; | 443 surfDesc.fFlags = (GrSurfaceFlags) desc.fFlags; |
441 surfDesc.fWidth = desc.fWidth; | 444 surfDesc.fWidth = desc.fWidth; |
442 surfDesc.fHeight = desc.fHeight; | 445 surfDesc.fHeight = desc.fHeight; |
443 surfDesc.fConfig = desc.fConfig; | 446 surfDesc.fConfig = desc.fConfig; |
444 surfDesc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount() ); | 447 surfDesc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount() ); |
445 bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFla g); | 448 bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFla g); |
446 // FIXME: this should be calling resolve_origin(), but Chrome code is curre ntly | 449 // FIXME: this should be calling resolve_origin(), but Chrome code is curre ntly |
447 // assuming the old behaviour, which is that backend textures are always | 450 // assuming the old behaviour, which is that backend textures are always |
(...skipping 29 matching lines...) Expand all Loading... | |
477 idDesc.fRTFBOID = static_cast<GrGLuint>(wrapDesc.fRenderTargetHandle); | 480 idDesc.fRTFBOID = static_cast<GrGLuint>(wrapDesc.fRenderTargetHandle); |
478 idDesc.fMSColorRenderbufferID = 0; | 481 idDesc.fMSColorRenderbufferID = 0; |
479 idDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID; | 482 idDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID; |
480 switch (ownership) { | 483 switch (ownership) { |
481 case kAdopt_GrWrapOwnership: | 484 case kAdopt_GrWrapOwnership: |
482 idDesc.fLifeCycle = GrGpuResource::kAdopted_LifeCycle; | 485 idDesc.fLifeCycle = GrGpuResource::kAdopted_LifeCycle; |
483 break; | 486 break; |
484 case kBorrow_GrWrapOwnership: | 487 case kBorrow_GrWrapOwnership: |
485 idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle; | 488 idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle; |
486 break; | 489 break; |
487 } | 490 } |
488 idDesc.fSampleConfig = GrRenderTarget::kUnified_SampleConfig; | 491 idDesc.fSampleConfig = GrRenderTarget::kUnified_SampleConfig; |
489 | 492 |
490 GrSurfaceDesc desc; | 493 GrSurfaceDesc desc; |
491 desc.fConfig = wrapDesc.fConfig; | 494 desc.fConfig = wrapDesc.fConfig; |
492 desc.fFlags = kCheckAllocation_GrSurfaceFlag | kRenderTarget_GrSurfaceFlag; | 495 desc.fFlags = kCheckAllocation_GrSurfaceFlag | kRenderTarget_GrSurfaceFlag; |
493 desc.fWidth = wrapDesc.fWidth; | 496 desc.fWidth = wrapDesc.fWidth; |
494 desc.fHeight = wrapDesc.fHeight; | 497 desc.fHeight = wrapDesc.fHeight; |
495 desc.fSampleCnt = SkTMin(wrapDesc.fSampleCnt, this->caps()->maxSampleCount() ); | 498 desc.fSampleCnt = SkTMin(wrapDesc.fSampleCnt, this->caps()->maxSampleCount() ); |
496 desc.fOrigin = resolve_origin(wrapDesc.fOrigin, true); | 499 desc.fOrigin = resolve_origin(wrapDesc.fOrigin, true); |
497 | 500 |
498 return GrGLRenderTarget::CreateWrapped(this, desc, idDesc, wrapDesc.fStencil Bits); | 501 return GrGLRenderTarget::CreateWrapped(this, desc, idDesc, wrapDesc.fStencil Bits); |
499 } | 502 } |
500 | 503 |
501 //////////////////////////////////////////////////////////////////////////////// | 504 //////////////////////////////////////////////////////////////////////////////// |
502 bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height, | 505 bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height, |
503 size_t rowBytes, GrPixelConfig srcConfig, | 506 GrPixelConfig srcConfig, |
504 DrawPreference* drawPreference, | 507 DrawPreference* drawPreference, |
505 WritePixelTempDrawInfo* tempDrawInfo) { | 508 WritePixelTempDrawInfo* tempDrawInfo) { |
506 if (kIndex_8_GrPixelConfig == srcConfig || GrPixelConfigIsCompressed(dstSurf ace->config())) { | 509 if (kIndex_8_GrPixelConfig == srcConfig || GrPixelConfigIsCompressed(dstSurf ace->config())) { |
507 return false; | 510 return false; |
508 } | 511 } |
509 | 512 |
510 // This subclass only allows writes to textures. If the dst is not a texture we have to draw | 513 // This subclass only allows writes to textures. If the dst is not a texture we have to draw |
511 // into it. We could use glDrawPixels on GLs that have it, but we don't toda y. | 514 // into it. We could use glDrawPixels on GLs that have it, but we don't toda y. |
512 if (!dstSurface->asTexture()) { | 515 if (!dstSurface->asTexture()) { |
513 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); | 516 ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
553 if (!this->glCaps().unpackFlipYSupport() && | 556 if (!this->glCaps().unpackFlipYSupport() && |
554 kBottomLeft_GrSurfaceOrigin == dstSurface->origin()) { | 557 kBottomLeft_GrSurfaceOrigin == dstSurface->origin()) { |
555 ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference); | 558 ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference); |
556 } | 559 } |
557 | 560 |
558 return true; | 561 return true; |
559 } | 562 } |
560 | 563 |
561 bool GrGLGpu::onWritePixels(GrSurface* surface, | 564 bool GrGLGpu::onWritePixels(GrSurface* surface, |
562 int left, int top, int width, int height, | 565 int left, int top, int width, int height, |
563 GrPixelConfig config, const void* buffer, | 566 GrPixelConfig config, |
564 size_t rowBytes) { | 567 const SkTArray<SkMipMapLevel>& texels) { |
565 GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture()); | 568 GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture()); |
566 if (!glTex) { | 569 if (!glTex) { |
567 return false; | 570 return false; |
568 } | 571 } |
569 | 572 |
570 // OpenGL doesn't do sRGB <-> linear conversions when reading and writing pi xels. | 573 // OpenGL doesn't do sRGB <-> linear conversions when reading and writing pi xels. |
571 if (GrPixelConfigIsSRGB(surface->config()) != GrPixelConfigIsSRGB(config)) { | 574 if (GrPixelConfigIsSRGB(surface->config()) != GrPixelConfigIsSRGB(config)) { |
572 return false; | 575 return false; |
573 } | 576 } |
574 | 577 |
575 this->setScratchTextureUnit(); | 578 this->setScratchTextureUnit(); |
576 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, glTex->textureID())); | 579 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, glTex->textureID())); |
577 | 580 |
578 bool success = false; | 581 bool success = false; |
579 if (GrPixelConfigIsCompressed(glTex->desc().fConfig)) { | 582 if (GrPixelConfigIsCompressed(glTex->desc().fConfig)) { |
580 // We check that config == desc.fConfig in GrGLGpu::canWriteTexturePixel s() | 583 // We check that config == desc.fConfig in GrGLGpu::canWriteTexturePixel s() |
581 SkASSERT(config == glTex->desc().fConfig); | 584 SkASSERT(config == glTex->desc().fConfig); |
582 success = this->uploadCompressedTexData(glTex->desc(), buffer, false, le ft, top, width, | 585 success = this->uploadCompressedTexData(glTex->desc(), texels, false, le ft, top, width, |
583 height); | 586 height); |
584 } else { | 587 } else { |
585 success = this->uploadTexData(glTex->desc(), false, left, top, width, he ight, config, | 588 success = this->uploadTexData(glTex->desc(), false, left, top, width, he ight, config, texels); |
586 buffer, rowBytes); | |
587 } | 589 } |
588 | 590 |
589 if (success) { | 591 return success; |
590 glTex->texturePriv().dirtyMipMaps(true); | |
591 return true; | |
592 } | |
593 | |
594 return false; | |
595 } | 592 } |
596 | 593 |
597 static inline GrGLenum check_alloc_error(const GrSurfaceDesc& desc, | 594 static inline GrGLenum check_alloc_error(const GrSurfaceDesc& desc, |
598 const GrGLInterface* interface) { | 595 const GrGLInterface* interface) { |
599 if (SkToBool(desc.fFlags & kCheckAllocation_GrSurfaceFlag)) { | 596 if (SkToBool(desc.fFlags & kCheckAllocation_GrSurfaceFlag)) { |
600 return GR_GL_GET_ERROR(interface); | 597 return GR_GL_GET_ERROR(interface); |
601 } else { | 598 } else { |
602 return CHECK_ALLOC_ERROR(interface); | 599 return CHECK_ALLOC_ERROR(interface); |
603 } | 600 } |
604 } | 601 } |
605 | 602 |
606 bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc, | 603 /** |
607 bool isNewTexture, | 604 * Determines if TexStorage can be used when creating a texture. |
608 int left, int top, int width, int height, | 605 * |
609 GrPixelConfig dataConfig, | 606 * @param caps The capabilities of the GL device. |
610 const void* data, | 607 * @param standard The GL standard in use. |
611 size_t rowBytes) { | 608 * @param desc The surface descriptor for the texture being created. |
612 SkASSERT(data || isNewTexture); | 609 */ |
613 | 610 static bool can_use_tex_storage(const GrGLCaps& caps, const GrGLStandard& standa rd, |
614 // If we're uploading compressed data then we should be using uploadCompress edTexData | 611 const GrSurfaceDesc& desc) { |
615 SkASSERT(!GrPixelConfigIsCompressed(dataConfig)); | 612 bool useTexStorage = caps.texStorageSupport(); |
616 | 613 if (useTexStorage && kGL_GrGLStandard == standard) { |
617 size_t bpp = GrBytesPerPixel(dataConfig); | |
618 if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bpp, & left, &top, | |
619 &width, &height, &data, &rowBytes )) { | |
620 return false; | |
621 } | |
622 size_t trimRowBytes = width * bpp; | |
623 | |
624 // in case we need a temporary, trimmed copy of the src pixels | |
625 SkAutoSMalloc<128 * 128> tempStorage; | |
626 | |
627 // We currently lazily create MIPMAPs when the we see a draw with | |
628 // GrTextureParams::kMipMap_FilterMode. Using texture storage requires that the | |
629 // MIP levels are all created when the texture is created. So for now we don 't use | |
630 // texture storage. | |
631 bool useTexStorage = false && | |
632 isNewTexture && | |
633 this->glCaps().texStorageSupport(); | |
634 | |
635 if (useTexStorage && kGL_GrGLStandard == this->glStandard()) { | |
636 // 565 is not a sized internal format on desktop GL. So on desktop with | 614 // 565 is not a sized internal format on desktop GL. So on desktop with |
637 // 565 we always use an unsized internal format to let the system pick | 615 // 565 we always use an unsized internal format to let the system pick |
638 // the best sized format to convert the 565 data to. Since TexStorage | 616 // the best sized format to convert the 565 data to. Since TexStorage |
639 // only allows sized internal formats we will instead use TexImage2D. | 617 // only allows sized internal formats we will instead use TexImage2D. |
640 useTexStorage = desc.fConfig != kRGB_565_GrPixelConfig; | 618 useTexStorage = desc.fConfig != kRGB_565_GrPixelConfig; |
641 } | 619 } |
642 | 620 |
643 GrGLenum internalFormat = 0x0; // suppress warning | 621 return useTexStorage; |
644 GrGLenum externalFormat = 0x0; // suppress warning | 622 } |
645 GrGLenum externalType = 0x0; // suppress warning | |
646 | 623 |
624 /** | |
625 * Determines if sized internal formats are available for the texture being crea ted. | |
626 * | |
627 * @param useTexStorage The result of a call to can_use_tex_storage(). | |
628 * @param caps The capabilities of the GL device. | |
629 * @param standard The GL standard in use. | |
630 * @param version The GL version in use. | |
631 * @param dataConfig The pixel configuration for the texture being created. | |
632 */ | |
633 static bool can_use_sized_format(bool useTexStorage, const GrGLCaps& caps, | |
634 const GrGLStandard& standard, const GrGLVersion & version, | |
635 GrPixelConfig dataConfig) { | |
647 // glTexStorage requires sized internal formats on both desktop and ES. ES2 requires an unsized | 636 // glTexStorage requires sized internal formats on both desktop and ES. ES2 requires an unsized |
648 // format for glTexImage, unlike ES3 and desktop. | 637 // format for glTexImage, unlike ES3 and desktop. |
649 bool useSizedFormat = useTexStorage; | 638 bool useSizedFormat = useTexStorage; |
650 if (kGL_GrGLStandard == this->glStandard() || | 639 if (kGL_GrGLStandard == standard || |
651 (this->glVersion() >= GR_GL_VER(3, 0) && | 640 (version >= GR_GL_VER(3, 0) && |
652 // ES3 only works with sized BGRA8 format if "GL_APPLE_texture_format_B GRA8888" enabled | 641 // ES3 only works with sized BGRA8 format if "GL_APPLE_texture_format_B GRA8888" enabled |
653 (kBGRA_8888_GrPixelConfig != dataConfig || !this->glCaps().bgraIsIntern alFormat()))) { | 642 (kBGRA_8888_GrPixelConfig != dataConfig || !caps.bgraIsInternalFormat() ))) { |
654 useSizedFormat = true; | 643 useSizedFormat = true; |
655 } | 644 } |
656 | 645 |
657 if (!this->configToGLFormats(dataConfig, useSizedFormat, &internalFormat, | 646 return useSizedFormat; |
658 &externalFormat, &externalType)) { | 647 } |
659 return false; | |
660 } | |
661 | 648 |
662 /* | 649 /** |
663 * check whether to allocate a temporary buffer for flipping y or | 650 * Prior to a texture being created, the image may need to be flipped vertically . This function |
664 * because our srcData has extra bytes past each row. If so, we need | 651 * prepares the texels for texture creation. |
665 * to trim those off here, since GL ES may not let us specify | 652 * |
666 * GL_UNPACK_ROW_LENGTH. | 653 * @param desc The surface descriptor for the texture being create d. |
667 */ | 654 * @param caps The capabilities of the GL device. |
668 bool restoreGLRowLength = false; | 655 * @param interface The GL interface in use. |
669 bool swFlipY = false; | 656 * @param swFlipY Should software be used when flipping a texture ver tically? |
670 bool glFlipY = false; | 657 * @param glFlipY Should GL be used when flipping a texture verticall y? |
671 if (data) { | 658 * @param width The width of the texture in texels. |
672 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { | 659 * @param height The height of the texture in texels. |
673 if (this->glCaps().unpackFlipYSupport()) { | 660 * @param bpp The bits per pixel (or texel, really) of the textur e. |
674 glFlipY = true; | 661 * @param texels An array of mipmap levels which contain the texel d ata at that level. |
675 } else { | 662 * @param tempStorage In the case where the image needs to be flipped ver tically, it will |
676 swFlipY = true; | 663 * use tempStorage as a buffer. |
677 } | 664 * @param restoreGLRowLength After the texture is created, will the GL row lengt h unpacking need |
665 * to be restored? | |
666 */ | |
667 static void prepare_image_for_writing_to_texture(const GrSurfaceDesc& desc, cons t GrGLCaps& caps, | |
668 const GrGLInterface& interface, bool swFlipY, | |
669 bool glFlipY, int bpp, | |
670 SkTArray<SkMipMapLevel>& texels , | |
671 SkAutoSMalloc<128 * 128>& tempS torage, | |
672 bool* restoreGLRowLength) { | |
673 for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLe vel++) { | |
674 if (texels[currentMipLevel].fTexels == nullptr) { | |
675 continue; | |
678 } | 676 } |
679 if (this->glCaps().unpackRowLengthSupport() && !swFlipY) { | 677 |
678 const size_t trimRowBytes = texels[currentMipLevel].fWidth * bpp; | |
679 | |
680 /* | |
681 * check whether to allocate a temporary buffer for flipping y or | |
682 * because our srcData has extra bytes past each row. If so, we need | |
683 * to trim those off here, since GL ES may not let us specify | |
684 * GL_UNPACK_ROW_LENGTH. | |
685 */ | |
686 *restoreGLRowLength = false; | |
687 | |
688 const size_t rowBytes = texels[currentMipLevel].fRowBytes; | |
689 if (caps.unpackRowLengthSupport() && !swFlipY) { | |
680 // can't use this for flipping, only non-neg values allowed. :( | 690 // can't use this for flipping, only non-neg values allowed. :( |
681 if (rowBytes != trimRowBytes) { | 691 if (rowBytes != trimRowBytes) { |
682 GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp); | 692 GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp); |
683 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength)); | 693 GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowL ength)); |
684 restoreGLRowLength = true; | 694 *restoreGLRowLength = true; |
685 } | 695 } |
686 } else { | 696 } else { |
687 if (trimRowBytes != rowBytes || swFlipY) { | 697 if (trimRowBytes != rowBytes || swFlipY) { |
698 const uint32_t height = texels[currentMipLevel].fHeight; | |
688 // copy data into our new storage, skipping the trailing bytes | 699 // copy data into our new storage, skipping the trailing bytes |
689 size_t trimSize = height * trimRowBytes; | 700 const size_t trimSize = height * trimRowBytes; |
690 const char* src = (const char*)data; | 701 const char* src = (const char*)texels[currentMipLevel].fTexels; |
691 if (swFlipY) { | 702 if (swFlipY && height >= 1) { |
692 src += (height - 1) * rowBytes; | 703 src += (height - 1) * rowBytes; |
693 } | 704 } |
694 char* dst = (char*)tempStorage.reset(trimSize); | 705 char* dst = (char*)tempStorage.reset(trimSize); |
695 for (int y = 0; y < height; y++) { | 706 for (uint32_t y = 0; y < height; y++) { |
696 memcpy(dst, src, trimRowBytes); | 707 memcpy(dst, src, trimRowBytes); |
697 if (swFlipY) { | 708 if (swFlipY) { |
698 src -= rowBytes; | 709 src -= rowBytes; |
699 } else { | 710 } else { |
700 src += rowBytes; | 711 src += rowBytes; |
701 } | 712 } |
702 dst += trimRowBytes; | 713 dst += trimRowBytes; |
703 } | 714 } |
704 // now point data to our copied version | 715 // now point data to our copied version |
705 data = tempStorage.get(); | 716 texels[currentMipLevel] = SkMipMapLevel(tempStorage.get(), trimR owBytes, |
717 texels[currentMipLevel]. fWidth, | |
718 texels[currentMipLevel]. fHeight); | |
706 } | 719 } |
707 } | 720 } |
708 if (glFlipY) { | 721 if (glFlipY) { |
709 GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE)); | 722 GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_TRUE)) ; |
710 } | 723 } |
711 GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, | 724 GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_ALIGNMENT, |
712 static_cast<GrGLint>(GrUnpackAlignment(dataConfig)))); | 725 static_cast<GrGLint>(GrUnpackAlignmen t(desc.fConfig)))); |
713 } | 726 } |
727 } | |
728 | |
729 /** | |
730 * Creates storage space for the texture and fills it with texels. | |
731 * | |
732 * @param desc The surface descriptor for the texture being created. | |
733 * @param interface The GL interface in use. | |
734 * @param useTexStorage The result of a call to can_use_tex_storage(). | |
735 * @param internalFormat The data format used for the internal storage of the te xture. | |
736 * @param externalFormat The data format used for the external storage of the te xture. | |
737 * @param externalType The type of the data used for the external storage of t he texture. | |
738 * @param texels The texel data of the texture being created. | |
739 * @param succeeded Set to true if allocating and populating the texture co mpleted | |
740 * without error. | |
741 */ | |
742 static void allocate_and_populate_uncompressed_texture(const GrSurfaceDesc& desc , | |
743 const GrGLInterface& inte rface, | |
744 bool useTexStorage, | |
745 GrGLenum internalFormat, | |
746 GrGLenum externalFormat, | |
747 GrGLenum externalType, | |
748 const SkTArray<SkMipMapLe vel>& texels, | |
749 bool* succeeded) { | |
750 CLEAR_ERROR_BEFORE_ALLOC(&interface); | |
751 if (useTexStorage) { | |
752 // We never resize or change formats of textures. | |
753 GL_ALLOC_CALL(&interface, | |
754 TexStorage2D(GR_GL_TEXTURE_2D, | |
755 texels.count(), | |
756 internalFormat, | |
757 desc.fWidth, desc.fHeight)); | |
758 | |
759 GrGLenum error = check_alloc_error(desc, &interface); | |
760 if (error != GR_GL_NO_ERROR) { | |
761 *succeeded = false; | |
762 } else { | |
763 for (int currentMipLevel = 0; currentMipLevel < texels.count(); curr entMipLevel++) { | |
764 const void* currentMipData = texels[currentMipLevel].fTexels; | |
765 if (currentMipData == nullptr) { | |
766 continue; | |
767 } | |
768 | |
769 GR_GL_CALL(&interface, | |
770 TexSubImage2D(GR_GL_TEXTURE_2D, | |
771 currentMipLevel, | |
772 0, // left | |
773 0, // top | |
774 texels[currentMipLevel].fWidth, | |
775 texels[currentMipLevel].fHeight, | |
776 externalFormat, externalType, | |
777 currentMipData)); | |
778 } | |
779 *succeeded = true; | |
780 } | |
781 } else { | |
782 *succeeded = true; | |
783 for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentM ipLevel++) { | |
784 GL_ALLOC_CALL(&interface, | |
785 TexImage2D(GR_GL_TEXTURE_2D, | |
786 currentMipLevel, | |
787 internalFormat, | |
788 texels[currentMipLevel].fWidth, | |
789 texels[currentMipLevel].fHeight, | |
790 0, // border | |
791 externalFormat, externalType, | |
792 texels[currentMipLevel].fTexels)); | |
793 GrGLenum error = check_alloc_error(desc, &interface); | |
794 if (error != GR_GL_NO_ERROR) { | |
795 *succeeded = false; | |
796 break; | |
797 } | |
798 } | |
799 } | |
800 } | |
801 | |
802 /** | |
803 * Creates storage space for the texture and fills it with texels. | |
804 * | |
805 * @param desc The surface descriptor for the texture being created. | |
806 * @param interface The GL interface in use. | |
807 * @param useTexStorage The result of a call to can_use_tex_storage(). | |
808 * @param internalFormat The data format used for the internal storage of the te xture. | |
809 * @param texels The texel data of the texture being created. | |
810 */ | |
811 static bool allocate_and_populate_compressed_texture(const GrSurfaceDesc& desc, | |
812 const GrGLInterface& interf ace, | |
813 bool useTexStorage, GrGLenu m internalFormat, | |
814 const SkTArray<SkMipMapLeve l>& texels) { | |
815 CLEAR_ERROR_BEFORE_ALLOC(&interface); | |
816 if (useTexStorage) { | |
817 // We never resize or change formats of textures. | |
818 GL_ALLOC_CALL(&interface, | |
819 TexStorage2D(GR_GL_TEXTURE_2D, | |
820 texels.count(), | |
821 internalFormat, | |
822 desc.fWidth, desc.fHeight)); | |
823 GrGLenum error = check_alloc_error(desc, &interface); | |
824 if (error != GR_GL_NO_ERROR) { | |
825 return false; | |
826 } else { | |
827 for (int currentMipLevel = 0; currentMipLevel < texels.count(); curr entMipLevel++) { | |
828 const void* currentMipData = texels[currentMipLevel].fTexels; | |
829 if (currentMipData == nullptr) { | |
830 continue; | |
831 } | |
832 | |
833 const uint32_t width = texels[currentMipLevel].fWidth; | |
834 const uint32_t height = texels[currentMipLevel].fHeight; | |
835 | |
836 // Make sure that the width and height that we pass to OpenGL | |
837 // is a multiple of the block size. | |
838 size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, width , height); | |
839 GR_GL_CALL(&interface, CompressedTexSubImage2D(GR_GL_TEXTURE_2D, | |
840 currentMipLevel, | |
841 0, // left | |
842 0, // top | |
843 width, height, | |
844 internalFormat, S kToInt(dataSize), | |
845 currentMipData)); | |
846 } | |
847 } | |
848 } else { | |
849 for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentM ipLevel++) { | |
850 const uint32_t width = texels[currentMipLevel].fWidth; | |
851 const uint32_t height = texels[currentMipLevel].fHeight; | |
852 | |
853 // Make sure that the width and height that we pass to OpenGL | |
854 // is a multiple of the block size. | |
855 size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, width, he ight); | |
856 | |
857 GL_ALLOC_CALL(&interface, | |
858 CompressedTexImage2D(GR_GL_TEXTURE_2D, | |
859 texels.count(), | |
860 internalFormat, | |
861 width, height, | |
862 0, // border | |
863 SkToInt(dataSize), | |
864 texels[currentMipLevel].fTexels)) ; | |
865 | |
866 GrGLenum error = check_alloc_error(desc, &interface); | |
867 if (error != GR_GL_NO_ERROR) { | |
868 return false; | |
869 } | |
870 } | |
871 } | |
872 return true; | |
873 } | |
874 | |
875 /** | |
876 * After a texture is created, any state which was altered during its creation | |
877 * needs to be restored. | |
878 * | |
879 * @param interface The GL interface to use. | |
880 * @param caps The capabilities of the GL device. | |
881 * @param restoreGLRowLength Should the row length unpacking be restored? | |
882 * @param glFlipY Did GL flip the texture vertically? | |
883 */ | |
884 static void restore_pixelstore_state(const GrGLInterface& interface, const GrGLC aps& caps, | |
885 bool restoreGLRowLength, bool glFlipY) { | |
886 if (restoreGLRowLength) { | |
887 SkASSERT(caps.unpackRowLengthSupport()); | |
888 GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0)); | |
889 } | |
890 if (glFlipY) { | |
891 GR_GL_CALL(&interface, PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE)); | |
892 } | |
893 } | |
894 | |
895 bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc, | |
896 bool isNewTexture, | |
897 int left, int top, int width, int height, | |
898 GrPixelConfig dataConfig, | |
899 const SkTArray<SkMipMapLevel>& texels) { | |
900 // If we're uploading compressed data then we should be using uploadCompress edTexData | |
901 SkASSERT(!GrPixelConfigIsCompressed(dataConfig)); | |
902 | |
903 SkTArray<SkMipMapLevel> texelsCopy(texels); | |
904 | |
905 for (int currentMipLevel = texelsCopy.count() - 1; currentMipLevel >= 0; cur rentMipLevel--) { | |
906 //SkASSERT(texelsCopy[currentMipLevel].fTexels || isNewTexture); | |
907 } | |
908 | |
909 | |
910 const GrGLInterface* interface = this->glInterface(); | |
911 if (interface == nullptr) { | |
912 return false; | |
913 } | |
914 const GrGLCaps& caps = this->glCaps(); | |
915 GrGLStandard standard = this->glStandard(); | |
916 GrGLVersion version = this->glVersion(); | |
917 | |
918 size_t bpp = GrBytesPerPixel(dataConfig); | |
919 for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLe vel++) { | |
920 if (texelsCopy[currentMipLevel].fTexels == nullptr) { | |
921 continue; | |
922 } | |
923 | |
924 if (texelsCopy[currentMipLevel].fHeight > std::numeric_limits<int>::max( ) | |
bsalomon
2015/09/30 18:01:29
SK_MaxI32
cblume
2015/10/08 09:27:57
Done.
| |
925 || texelsCopy[currentMipLevel].fWidth > std::numeric_limits<int>::ma x()) { | |
bsalomon
2015/09/30 18:01:29
SK_MaxI32
cblume
2015/10/08 09:27:57
Done.
| |
926 return false; | |
927 } | |
928 int currentMipHeight = texelsCopy[currentMipLevel].fHeight; | |
929 int currentMipWidth = texelsCopy[currentMipLevel].fWidth; | |
930 if (!GrSurfacePriv::AdjustWritePixelParams(desc.fWidth, desc.fHeight, bp p, &left, &top, | |
931 ¤tMipWidth, | |
932 ¤tMipHeight, | |
933 &texelsCopy[currentMipLevel].fTex els, | |
934 &texelsCopy[currentMipLevel].fRow Bytes)) { | |
935 return false; | |
936 } | |
937 if (currentMipWidth < 0 || currentMipHeight < 0) { | |
938 return false; | |
939 } | |
940 texelsCopy[currentMipLevel].fWidth = currentMipWidth; | |
941 texelsCopy[currentMipLevel].fHeight = currentMipHeight; | |
942 } | |
943 | |
944 bool useTexStorage = can_use_tex_storage(caps, standard, desc); | |
945 bool useSizedFormat = can_use_sized_format(useTexStorage, caps, standard, ve rsion, dataConfig); | |
946 | |
947 GrGLenum internalFormat = 0x0; // suppress warning | |
948 GrGLenum externalFormat = 0x0; // suppress warning | |
949 GrGLenum externalType = 0x0; // suppress warning | |
950 | |
951 if (!this->configToGLFormats(dataConfig, useSizedFormat, &internalFormat, | |
952 &externalFormat, &externalType)) { | |
953 return false; | |
954 } | |
955 | |
956 bool swFlipY = false; | |
957 bool glFlipY = false; | |
958 | |
959 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { | |
960 if (caps.unpackFlipYSupport()) { | |
961 glFlipY = true; | |
962 } else { | |
963 swFlipY = true; | |
964 } | |
965 } | |
966 | |
967 bool restoreGLRowLength = false; | |
968 | |
969 // in case we need a temporary, trimmed copy of the src pixels | |
970 SkAutoSMalloc<128 * 128> tempStorage; | |
971 prepare_image_for_writing_to_texture(desc, caps, *interface, swFlipY, glFlip Y, bpp, texelsCopy, | |
972 tempStorage, &restoreGLRowLength); | |
714 bool succeeded = true; | 973 bool succeeded = true; |
715 if (isNewTexture && | 974 if (isNewTexture && |
716 0 == left && 0 == top && | 975 0 == left && 0 == top && |
717 desc.fWidth == width && desc.fHeight == height) { | 976 desc.fWidth == width && desc.fHeight == height) { |
718 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); | 977 allocate_and_populate_uncompressed_texture(desc, *interface, useTexStora ge, internalFormat, |
719 if (useTexStorage) { | 978 externalFormat, externalType, texelsCopy, |
720 // We never resize or change formats of textures. | 979 &succeeded); |
721 GL_ALLOC_CALL(this->glInterface(), | |
722 TexStorage2D(GR_GL_TEXTURE_2D, | |
723 1, // levels | |
724 internalFormat, | |
725 desc.fWidth, desc.fHeight)); | |
726 } else { | |
727 GL_ALLOC_CALL(this->glInterface(), | |
728 TexImage2D(GR_GL_TEXTURE_2D, | |
729 0, // level | |
730 internalFormat, | |
731 desc.fWidth, desc.fHeight, | |
732 0, // border | |
733 externalFormat, externalType, | |
734 data)); | |
735 } | |
736 GrGLenum error = check_alloc_error(desc, this->glInterface()); | |
737 if (error != GR_GL_NO_ERROR) { | |
738 succeeded = false; | |
739 } else { | |
740 // if we have data and we used TexStorage to create the texture, we | |
741 // now upload with TexSubImage. | |
742 if (data && useTexStorage) { | |
743 GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, | |
744 0, // level | |
745 left, top, | |
746 width, height, | |
747 externalFormat, externalType, | |
748 data)); | |
749 } | |
750 } | |
751 } else { | 980 } else { |
752 if (swFlipY || glFlipY) { | 981 if (swFlipY || glFlipY) { |
753 top = desc.fHeight - (top + height); | 982 top = desc.fHeight - (top + height); |
754 } | 983 } |
755 GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, | 984 for (int currentMipLevel = 0; currentMipLevel < texelsCopy.count(); curr entMipLevel++) { |
756 0, // level | 985 if (texelsCopy[currentMipLevel].fTexels == nullptr) { |
757 left, top, | 986 continue; |
758 width, height, | 987 } |
759 externalFormat, externalType, data)); | 988 |
760 } | 989 GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, |
761 | 990 currentMipLevel, |
762 if (restoreGLRowLength) { | 991 left, top, |
763 SkASSERT(this->glCaps().unpackRowLengthSupport()); | 992 texelsCopy[currentMipLevel].fWidth, |
764 GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0)); | 993 texelsCopy[currentMipLevel].fHeight, |
765 } | 994 externalFormat, externalType, |
766 if (glFlipY) { | 995 texelsCopy[currentMipLevel].fTexels)); |
767 GL_CALL(PixelStorei(GR_GL_UNPACK_FLIP_Y, GR_GL_FALSE)); | 996 } |
768 } | 997 } |
998 | |
999 restore_pixelstore_state(*interface, caps, restoreGLRowLength, glFlipY); | |
1000 | |
769 return succeeded; | 1001 return succeeded; |
770 } | 1002 } |
771 | 1003 |
772 // TODO: This function is using a lot of wonky semantics like, if width == -1 | 1004 // TODO: This function is using a lot of wonky semantics like, if width == -1 |
773 // then set width = desc.fWdith ... blah. A better way to do it might be to | 1005 // then set width = desc.fWdith ... blah. A better way to do it might be to |
774 // create a CompressedTexData struct that takes a desc/ptr and figures out | 1006 // create a CompressedTexData struct that takes a desc/ptr and figures out |
775 // the proper upload semantics. Then users can construct this function how they | 1007 // the proper upload semantics. Then users can construct this function how they |
776 // see fit if they want to go against the "standard" way to do it. | 1008 // see fit if they want to go against the "standard" way to do it. |
777 bool GrGLGpu::uploadCompressedTexData(const GrSurfaceDesc& desc, | 1009 bool GrGLGpu::uploadCompressedTexData(const GrSurfaceDesc& desc, |
778 const void* data, | 1010 const SkTArray<SkMipMapLevel>& texels, |
779 bool isNewTexture, | 1011 bool isNewTexture, |
780 int left, int top, int width, int height) { | 1012 int left, int top, int width, int height) { |
781 SkASSERT(data || isNewTexture); | 1013 SkASSERT(isNewTexture); |
782 | 1014 |
783 // No support for software flip y, yet... | 1015 // No support for software flip y, yet... |
784 SkASSERT(kBottomLeft_GrSurfaceOrigin != desc.fOrigin); | 1016 SkASSERT(kBottomLeft_GrSurfaceOrigin != desc.fOrigin); |
785 | 1017 |
1018 const GrGLInterface* interface = this->glInterface(); | |
1019 if (interface == nullptr) { | |
bsalomon
2015/09/30 18:01:29
This can't happen, an interface is required to cre
cblume
2015/10/08 09:27:57
Done.
| |
1020 return false; | |
1021 } | |
1022 const GrGLCaps& caps = this->glCaps(); | |
1023 GrGLStandard standard = this->glStandard(); | |
1024 | |
786 if (-1 == width) { | 1025 if (-1 == width) { |
787 width = desc.fWidth; | 1026 width = desc.fWidth; |
788 } | 1027 } |
789 #ifdef SK_DEBUG | 1028 #ifdef SK_DEBUG |
790 else { | 1029 else { |
791 SkASSERT(width <= desc.fWidth); | 1030 SkASSERT(width <= desc.fWidth); |
792 } | 1031 } |
793 #endif | 1032 #endif |
794 | 1033 |
795 if (-1 == height) { | 1034 if (-1 == height) { |
796 height = desc.fHeight; | 1035 height = desc.fHeight; |
797 } | 1036 } |
798 #ifdef SK_DEBUG | 1037 #ifdef SK_DEBUG |
799 else { | 1038 else { |
800 SkASSERT(height <= desc.fHeight); | 1039 SkASSERT(height <= desc.fHeight); |
801 } | 1040 } |
802 #endif | 1041 #endif |
803 | 1042 |
804 // Make sure that the width and height that we pass to OpenGL | 1043 bool useTexStorage = can_use_tex_storage(caps, standard, desc); |
805 // is a multiple of the block size. | |
806 size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, width, height); | |
807 | 1044 |
808 // We only need the internal format for compressed 2D textures. | 1045 // We only need the internal format for compressed 2D textures. |
809 GrGLenum internalFormat = 0; | 1046 GrGLenum internalFormat = 0; |
810 if (!this->configToGLFormats(desc.fConfig, false, &internalFormat, nullptr, nullptr)) { | 1047 if (!this->configToGLFormats(desc.fConfig, false, &internalFormat, nullptr, nullptr)) { |
811 return false; | 1048 return false; |
812 } | 1049 } |
813 | 1050 |
814 if (isNewTexture) { | 1051 if (isNewTexture) { |
815 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); | 1052 return allocate_and_populate_compressed_texture(desc, *interface, useTex Storage, |
816 GL_ALLOC_CALL(this->glInterface(), | 1053 internalFormat, texels); |
817 CompressedTexImage2D(GR_GL_TEXTURE_2D, | |
818 0, // level | |
819 internalFormat, | |
820 width, height, | |
821 0, // border | |
822 SkToInt(dataSize), | |
823 data)); | |
824 GrGLenum error = check_alloc_error(desc, this->glInterface()); | |
825 if (error != GR_GL_NO_ERROR) { | |
826 return false; | |
827 } | |
828 } else { | 1054 } else { |
829 // Paletted textures can't be updated. | 1055 // Paletted textures can't be updated. |
830 if (GR_GL_PALETTE8_RGBA8 == internalFormat) { | 1056 if (GR_GL_PALETTE8_RGBA8 == internalFormat) { |
831 return false; | 1057 return false; |
832 } | 1058 } |
833 GL_CALL(CompressedTexSubImage2D(GR_GL_TEXTURE_2D, | 1059 for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentM ipLevel++) { |
834 0, // level | 1060 if (texels[currentMipLevel].fTexels == nullptr) { |
835 left, top, | 1061 continue; |
836 width, height, | 1062 } |
837 internalFormat, | 1063 |
838 SkToInt(dataSize), | 1064 // Make sure that the width and height that we pass to OpenGL |
839 data)); | 1065 // is a multiple of the block size. |
1066 size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, width, he ight); | |
1067 GL_CALL(CompressedTexSubImage2D(GR_GL_TEXTURE_2D, | |
1068 currentMipLevel, | |
1069 left, top, | |
1070 texels[currentMipLevel].fWidth, | |
1071 texels[currentMipLevel].fHeight, | |
1072 internalFormat, | |
1073 dataSize, | |
1074 texels[currentMipLevel].fTexels)); | |
1075 } | |
840 } | 1076 } |
841 | 1077 |
842 return true; | 1078 return true; |
843 } | 1079 } |
844 | 1080 |
845 static bool renderbuffer_storage_msaa(const GrGLContext& ctx, | 1081 static bool renderbuffer_storage_msaa(const GrGLContext& ctx, |
846 int sampleCount, | 1082 int sampleCount, |
847 GrGLenum format, | 1083 GrGLenum format, |
848 int width, int height) { | 1084 int width, int height) { |
849 CLEAR_ERROR_BEFORE_ALLOC(ctx.interface()); | 1085 CLEAR_ERROR_BEFORE_ALLOC(ctx.interface()); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
935 GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, idDesc->fMSColorRenderbuffe rID)); | 1171 GL_CALL(BindRenderbuffer(GR_GL_RENDERBUFFER, idDesc->fMSColorRenderbuffe rID)); |
936 if (!renderbuffer_storage_msaa(*fGLContext, | 1172 if (!renderbuffer_storage_msaa(*fGLContext, |
937 desc.fSampleCnt, | 1173 desc.fSampleCnt, |
938 msColorFormat, | 1174 msColorFormat, |
939 desc.fWidth, desc.fHeight)) { | 1175 desc.fWidth, desc.fHeight)) { |
940 goto FAILED; | 1176 goto FAILED; |
941 } | 1177 } |
942 fStats.incRenderTargetBinds(); | 1178 fStats.incRenderTargetBinds(); |
943 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, idDesc->fRTFBOID)); | 1179 GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, idDesc->fRTFBOID)); |
944 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, | 1180 GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, |
945 GR_GL_COLOR_ATTACHMENT0, | 1181 GR_GL_COLOR_ATTACHMENT0, |
946 GR_GL_RENDERBUFFER, | 1182 GR_GL_RENDERBUFFER, |
947 idDesc->fMSColorRenderbufferID)); | 1183 idDesc->fMSColorRenderbufferID)); |
948 if ((desc.fFlags & kCheckAllocation_GrSurfaceFlag) || | 1184 if ((desc.fFlags & kCheckAllocation_GrSurfaceFlag) || |
949 !this->glCaps().isConfigVerifiedColorAttachment(desc.fConfig)) { | 1185 !this->glCaps().isConfigVerifiedColorAttachment(desc.fConfig)) { |
950 GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); | 1186 GL_CALL_RET(status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER)); |
951 if (status != GR_GL_FRAMEBUFFER_COMPLETE) { | 1187 if (status != GR_GL_FRAMEBUFFER_COMPLETE) { |
952 goto FAILED; | 1188 goto FAILED; |
953 } | 1189 } |
954 fGLContext->caps()->markConfigAsValidColorAttachment(desc.fConfig); | 1190 fGLContext->caps()->markConfigAsValidColorAttachment(desc.fConfig); |
955 } | 1191 } |
956 } | 1192 } |
957 fStats.incRenderTargetBinds(); | 1193 fStats.incRenderTargetBinds(); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
997 // SkDEBUGFAIL("null texture"); | 1233 // SkDEBUGFAIL("null texture"); |
998 return nullptr; | 1234 return nullptr; |
999 } | 1235 } |
1000 | 1236 |
1001 #if 0 && defined(SK_DEBUG) | 1237 #if 0 && defined(SK_DEBUG) |
1002 static size_t as_size_t(int x) { | 1238 static size_t as_size_t(int x) { |
1003 return x; | 1239 return x; |
1004 } | 1240 } |
1005 #endif | 1241 #endif |
1006 | 1242 |
1243 static GrGLTexture::IDDesc generate_and_bind_gl_texture(const GrGLInterface* int erface, | |
1244 GrGpuResource::LifeCycle lifeCycle) { | |
1245 GrGLTexture::IDDesc idDesc; | |
1246 GR_GL_CALL(interface, GenTextures(1, &idDesc.fTextureID)); | |
1247 idDesc.fLifeCycle = lifeCycle; | |
1248 return idDesc; | |
1249 } | |
1250 | |
1251 static GrGLTexture::TexParams set_initial_texture_params(const GrGLInterface* in terface) { | |
1252 // Some drivers like to know filter/wrap before seeing glTexImage2D. Some | |
1253 // drivers have a bug where an FBO won't be complete if it includes a | |
1254 // texture that is not mipmap complete (considering the filter in use). | |
1255 GrGLTexture::TexParams initialTexParams; | |
1256 // we only set a subset here so invalidate first | |
1257 initialTexParams.invalidate(); | |
1258 initialTexParams.fMinFilter = GR_GL_NEAREST; | |
1259 initialTexParams.fMagFilter = GR_GL_NEAREST; | |
1260 initialTexParams.fWrapS = GR_GL_CLAMP_TO_EDGE; | |
1261 initialTexParams.fWrapT = GR_GL_CLAMP_TO_EDGE; | |
1262 GR_GL_CALL(interface, TexParameteri(GR_GL_TEXTURE_2D, | |
1263 GR_GL_TEXTURE_MAG_FILTER, | |
1264 initialTexParams.fMagFilter)); | |
1265 GR_GL_CALL(interface, TexParameteri(GR_GL_TEXTURE_2D, | |
1266 GR_GL_TEXTURE_MIN_FILTER, | |
1267 initialTexParams.fMinFilter)); | |
1268 GR_GL_CALL(interface, TexParameteri(GR_GL_TEXTURE_2D, | |
1269 GR_GL_TEXTURE_WRAP_S, | |
1270 initialTexParams.fWrapS)); | |
1271 GR_GL_CALL(interface, TexParameteri(GR_GL_TEXTURE_2D, | |
1272 GR_GL_TEXTURE_WRAP_T, | |
1273 initialTexParams.fWrapT)); | |
1274 return initialTexParams; | |
1275 } | |
1276 | |
1007 GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc, | 1277 GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc, |
1008 GrGpuResource::LifeCycle lifeCycle, | 1278 GrGpuResource::LifeCycle lifeCycle, |
1009 const void* srcData, size_t rowBytes) { | 1279 const SkTArray<SkMipMapLevel>& texels) { |
1010 // We fail if the MSAA was requested and is not available. | 1280 // We fail if the MSAA was requested and is not available. |
1011 if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleC nt) { | 1281 if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleC nt) { |
1012 //SkDebugf("MSAA RT requested but not supported on this platform."); | 1282 //SkDebugf("MSAA RT requested but not supported on this platform."); |
1013 return return_null_texture(); | 1283 return return_null_texture(); |
1014 } | 1284 } |
1015 | 1285 |
1016 bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag); | 1286 bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag); |
1017 | 1287 |
1018 GrGLTexture::IDDesc idDesc; | 1288 GrGLTexture::IDDesc idDesc = generate_and_bind_gl_texture(this->glInterface( ), lifeCycle); |
1019 GL_CALL(GenTextures(1, &idDesc.fTextureID)); | |
1020 idDesc.fLifeCycle = lifeCycle; | |
1021 | |
1022 if (!idDesc.fTextureID) { | 1289 if (!idDesc.fTextureID) { |
1023 return return_null_texture(); | 1290 return return_null_texture(); |
1024 } | 1291 } |
1025 | 1292 |
1026 this->setScratchTextureUnit(); | 1293 this->setScratchTextureUnit(); |
1027 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, idDesc.fTextureID)); | 1294 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, idDesc.fTextureID)); |
1028 | 1295 |
1029 if (renderTarget && this->glCaps().textureUsageSupport()) { | 1296 if (renderTarget && this->glCaps().textureUsageSupport()) { |
1030 // provides a hint about how this texture will be used | 1297 // provides a hint about how this texture will be used |
1031 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, | 1298 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, |
1032 GR_GL_TEXTURE_USAGE, | 1299 GR_GL_TEXTURE_USAGE, |
1033 GR_GL_FRAMEBUFFER_ATTACHMENT)); | 1300 GR_GL_FRAMEBUFFER_ATTACHMENT)); |
1034 } | 1301 } |
1035 | 1302 |
1036 // Some drivers like to know filter/wrap before seeing glTexImage2D. Some | 1303 GrGLTexture::TexParams initialTexParams = set_initial_texture_params(this->g lInterface()); |
1037 // drivers have a bug where an FBO won't be complete if it includes a | 1304 |
1038 // texture that is not mipmap complete (considering the filter in use). | |
1039 GrGLTexture::TexParams initialTexParams; | |
1040 // we only set a subset here so invalidate first | |
1041 initialTexParams.invalidate(); | |
1042 initialTexParams.fMinFilter = GR_GL_NEAREST; | |
1043 initialTexParams.fMagFilter = GR_GL_NEAREST; | |
1044 initialTexParams.fWrapS = GR_GL_CLAMP_TO_EDGE; | |
1045 initialTexParams.fWrapT = GR_GL_CLAMP_TO_EDGE; | |
1046 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, | |
1047 GR_GL_TEXTURE_MAG_FILTER, | |
1048 initialTexParams.fMagFilter)); | |
1049 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, | |
1050 GR_GL_TEXTURE_MIN_FILTER, | |
1051 initialTexParams.fMinFilter)); | |
1052 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, | |
1053 GR_GL_TEXTURE_WRAP_S, | |
1054 initialTexParams.fWrapS)); | |
1055 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, | |
1056 GR_GL_TEXTURE_WRAP_T, | |
1057 initialTexParams.fWrapT)); | |
1058 if (!this->uploadTexData(desc, true, 0, 0, | 1305 if (!this->uploadTexData(desc, true, 0, 0, |
1059 desc.fWidth, desc.fHeight, | 1306 desc.fWidth, desc.fHeight, |
1060 desc.fConfig, srcData, rowBytes)) { | 1307 desc.fConfig, texels)) { |
1061 GL_CALL(DeleteTextures(1, &idDesc.fTextureID)); | 1308 GL_CALL(DeleteTextures(1, &idDesc.fTextureID)); |
1062 return return_null_texture(); | 1309 return return_null_texture(); |
1063 } | 1310 } |
1064 | 1311 |
1065 GrGLTexture* tex; | 1312 GrGLTexture* tex; |
1066 if (renderTarget) { | 1313 if (renderTarget) { |
1067 // unbind the texture from the texture unit before binding it to the fra me buffer | 1314 // unbind the texture from the texture unit before binding it to the fra me buffer |
1068 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, 0)); | 1315 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, 0)); |
1069 GrGLRenderTarget::IDDesc rtIDDesc; | 1316 GrGLRenderTarget::IDDesc rtIDDesc; |
1070 | 1317 |
1071 if (!this->createRenderTargetObjects(desc, lifeCycle, idDesc.fTextureID, &rtIDDesc)) { | 1318 if (!this->createRenderTargetObjects(desc, lifeCycle, idDesc.fTextureID, &rtIDDesc)) { |
1072 GL_CALL(DeleteTextures(1, &idDesc.fTextureID)); | 1319 GL_CALL(DeleteTextures(1, &idDesc.fTextureID)); |
1073 return return_null_texture(); | 1320 return return_null_texture(); |
1074 } | 1321 } |
1075 tex = new GrGLTextureRenderTarget(this, desc, idDesc, rtIDDesc); | 1322 tex = new GrGLTextureRenderTarget(this, desc, idDesc, rtIDDesc); |
1076 } else { | 1323 } else { |
1077 tex = new GrGLTexture(this, desc, idDesc); | 1324 tex = new GrGLTexture(this, desc, idDesc); |
1078 } | 1325 } |
1079 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); | 1326 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); |
1080 #ifdef TRACE_TEXTURE_CREATION | 1327 #ifdef TRACE_TEXTURE_CREATION |
1081 SkDebugf("--- new texture [%d] size=(%d %d) config=%d\n", | 1328 SkDebugf("--- new texture [%d] size=(%d %d) config=%d\n", |
1082 glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig); | 1329 glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig); |
1083 #endif | 1330 #endif |
1084 return tex; | 1331 return tex; |
1085 } | 1332 } |
1086 | 1333 |
1087 GrTexture* GrGLGpu::onCreateCompressedTexture(const GrSurfaceDesc& desc, | 1334 GrTexture* GrGLGpu::onCreateCompressedTexture(const GrSurfaceDesc& desc, |
1088 GrGpuResource::LifeCycle lifeCycle , | 1335 GrGpuResource::LifeCycle lifeCycle , |
1089 const void* srcData) { | 1336 const SkTArray<SkMipMapLevel>& tex els) { |
1090 // Make sure that we're not flipping Y. | 1337 // Make sure that we're not flipping Y. |
1091 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { | 1338 if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) { |
1092 return return_null_texture(); | 1339 return return_null_texture(); |
1093 } | 1340 } |
1094 | 1341 |
1095 GrGLTexture::IDDesc idDesc; | 1342 auto idDesc = generate_and_bind_gl_texture(this->glInterface(), lifeCycle); |
bsalomon
2015/09/30 18:01:29
-auto
cblume
2015/10/08 09:27:57
Done.
| |
1096 GL_CALL(GenTextures(1, &idDesc.fTextureID)); | |
1097 idDesc.fLifeCycle = lifeCycle; | |
1098 | |
1099 if (!idDesc.fTextureID) { | 1343 if (!idDesc.fTextureID) { |
1100 return return_null_texture(); | 1344 return return_null_texture(); |
1101 } | 1345 } |
1102 | 1346 |
1103 this->setScratchTextureUnit(); | 1347 this->setScratchTextureUnit(); |
1104 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, idDesc.fTextureID)); | 1348 GL_CALL(BindTexture(GR_GL_TEXTURE_2D, idDesc.fTextureID)); |
1105 | 1349 |
1106 // Some drivers like to know filter/wrap before seeing glTexImage2D. Some | 1350 auto initialTexParams = set_initial_texture_params(this->glInterface()); |
bsalomon
2015/09/30 18:01:29
-auto
cblume
2015/10/08 09:27:57
Done.
| |
1107 // drivers have a bug where an FBO won't be complete if it includes a | |
1108 // texture that is not mipmap complete (considering the filter in use). | |
1109 GrGLTexture::TexParams initialTexParams; | |
1110 // we only set a subset here so invalidate first | |
1111 initialTexParams.invalidate(); | |
1112 initialTexParams.fMinFilter = GR_GL_NEAREST; | |
1113 initialTexParams.fMagFilter = GR_GL_NEAREST; | |
1114 initialTexParams.fWrapS = GR_GL_CLAMP_TO_EDGE; | |
1115 initialTexParams.fWrapT = GR_GL_CLAMP_TO_EDGE; | |
1116 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, | |
1117 GR_GL_TEXTURE_MAG_FILTER, | |
1118 initialTexParams.fMagFilter)); | |
1119 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, | |
1120 GR_GL_TEXTURE_MIN_FILTER, | |
1121 initialTexParams.fMinFilter)); | |
1122 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, | |
1123 GR_GL_TEXTURE_WRAP_S, | |
1124 initialTexParams.fWrapS)); | |
1125 GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, | |
1126 GR_GL_TEXTURE_WRAP_T, | |
1127 initialTexParams.fWrapT)); | |
1128 | 1351 |
1129 if (!this->uploadCompressedTexData(desc, srcData)) { | 1352 if (!this->uploadCompressedTexData(desc, texels)) { |
1130 GL_CALL(DeleteTextures(1, &idDesc.fTextureID)); | 1353 GL_CALL(DeleteTextures(1, &idDesc.fTextureID)); |
1131 return return_null_texture(); | 1354 return return_null_texture(); |
1132 } | 1355 } |
1133 | 1356 |
1134 GrGLTexture* tex; | 1357 GrGLTexture* tex; |
1135 tex = new GrGLTexture(this, desc, idDesc); | 1358 tex = new GrGLTexture(this, desc, idDesc); |
1136 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); | 1359 tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); |
1137 #ifdef TRACE_TEXTURE_CREATION | 1360 #ifdef TRACE_TEXTURE_CREATION |
1138 SkDebugf("--- new compressed texture [%d] size=(%d %d) config=%d\n", | 1361 SkDebugf("--- new compressed texture [%d] size=(%d %d) config=%d\n", |
1139 glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig); | 1362 glTexDesc.fTextureID, desc.fWidth, desc.fHeight, desc.fConfig); |
(...skipping 1403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2543 *internalFormat = GR_GL_ALPHA; | 2766 *internalFormat = GR_GL_ALPHA; |
2544 } | 2767 } |
2545 *externalFormat = GR_GL_ALPHA; | 2768 *externalFormat = GR_GL_ALPHA; |
2546 } | 2769 } |
2547 if (kGL_GrGLStandard == this->glStandard() || this->glVersion() >= G R_GL_VER(3, 0)) { | 2770 if (kGL_GrGLStandard == this->glStandard() || this->glVersion() >= G R_GL_VER(3, 0)) { |
2548 *externalType = GR_GL_HALF_FLOAT; | 2771 *externalType = GR_GL_HALF_FLOAT; |
2549 } else { | 2772 } else { |
2550 *externalType = GR_GL_HALF_FLOAT_OES; | 2773 *externalType = GR_GL_HALF_FLOAT_OES; |
2551 } | 2774 } |
2552 break; | 2775 break; |
2553 | 2776 |
2554 case kRGBA_half_GrPixelConfig: | 2777 case kRGBA_half_GrPixelConfig: |
2555 *internalFormat = GR_GL_RGBA16F; | 2778 *internalFormat = GR_GL_RGBA16F; |
2556 *externalFormat = GR_GL_RGBA; | 2779 *externalFormat = GR_GL_RGBA; |
2557 if (kGL_GrGLStandard == this->glStandard() || this->glVersion() >= G R_GL_VER(3, 0)) { | 2780 if (kGL_GrGLStandard == this->glStandard() || this->glVersion() >= G R_GL_VER(3, 0)) { |
2558 *externalType = GR_GL_HALF_FLOAT; | 2781 *externalType = GR_GL_HALF_FLOAT; |
2559 } else { | 2782 } else { |
2560 *externalType = GR_GL_HALF_FLOAT_OES; | 2783 *externalType = GR_GL_HALF_FLOAT_OES; |
2561 } | 2784 } |
2562 break; | 2785 break; |
2563 | 2786 |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2738 } | 2961 } |
2739 | 2962 |
2740 bool GrGLGpu::onCopySurface(GrSurface* dst, | 2963 bool GrGLGpu::onCopySurface(GrSurface* dst, |
2741 GrSurface* src, | 2964 GrSurface* src, |
2742 const SkIRect& srcRect, | 2965 const SkIRect& srcRect, |
2743 const SkIPoint& dstPoint) { | 2966 const SkIPoint& dstPoint) { |
2744 if (src->asTexture() && dst->asRenderTarget()) { | 2967 if (src->asTexture() && dst->asRenderTarget()) { |
2745 this->copySurfaceAsDraw(dst, src, srcRect, dstPoint); | 2968 this->copySurfaceAsDraw(dst, src, srcRect, dstPoint); |
2746 return true; | 2969 return true; |
2747 } | 2970 } |
2748 | 2971 |
2749 if (can_copy_texsubimage(dst, src, this)) { | 2972 if (can_copy_texsubimage(dst, src, this)) { |
2750 this->copySurfaceAsCopyTexSubImage(dst, src, srcRect, dstPoint); | 2973 this->copySurfaceAsCopyTexSubImage(dst, src, srcRect, dstPoint); |
2751 return true; | 2974 return true; |
2752 } | 2975 } |
2753 | 2976 |
2754 if (can_blit_framebuffer(dst, src, this)) { | 2977 if (can_blit_framebuffer(dst, src, this)) { |
2755 return this->copySurfaceAsBlitFramebuffer(dst, src, srcRect, dstPoint); | 2978 return this->copySurfaceAsBlitFramebuffer(dst, src, srcRect, dstPoint); |
2756 } | 2979 } |
2757 | 2980 |
2758 return false; | 2981 return false; |
2759 } | 2982 } |
2760 | 2983 |
2761 | 2984 |
2762 void GrGLGpu::createCopyProgram() { | 2985 void GrGLGpu::createCopyProgram() { |
2763 const char* version = GrGLGetGLSLVersionDecl(this->ctxInfo()); | 2986 const char* version = GrGLGetGLSLVersionDecl(this->ctxInfo()); |
2764 | 2987 |
2765 GrGLShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kAttribute_T ypeModifier); | 2988 GrGLShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kAttribute_T ypeModifier); |
2766 GrGLShaderVar uTexCoordXform("u_texCoordXform", kVec4f_GrSLType, | 2989 GrGLShaderVar uTexCoordXform("u_texCoordXform", kVec4f_GrSLType, |
2767 GrShaderVar::kUniform_TypeModifier); | 2990 GrShaderVar::kUniform_TypeModifier); |
2768 GrGLShaderVar uPosXform("u_posXform", kVec4f_GrSLType, GrShaderVar::kUniform _TypeModifier); | 2991 GrGLShaderVar uPosXform("u_posXform", kVec4f_GrSLType, GrShaderVar::kUniform _TypeModifier); |
2769 GrGLShaderVar uTexture("u_texture", kSampler2D_GrSLType, GrShaderVar::kUnifo rm_TypeModifier); | 2992 GrGLShaderVar uTexture("u_texture", kSampler2D_GrSLType, GrShaderVar::kUnifo rm_TypeModifier); |
2770 GrGLShaderVar vTexCoord("v_texCoord", kVec2f_GrSLType, GrShaderVar::kVarying Out_TypeModifier); | 2993 GrGLShaderVar vTexCoord("v_texCoord", kVec2f_GrSLType, GrShaderVar::kVarying Out_TypeModifier); |
2771 GrGLShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_T ypeModifier); | 2994 GrGLShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_T ypeModifier); |
2772 | 2995 |
2773 SkString vshaderTxt(version); | 2996 SkString vshaderTxt(version); |
2774 aVertex.appendDecl(this->ctxInfo(), &vshaderTxt); | 2997 aVertex.appendDecl(this->ctxInfo(), &vshaderTxt); |
2775 vshaderTxt.append(";"); | 2998 vshaderTxt.append(";"); |
2776 uTexCoordXform.appendDecl(this->ctxInfo(), &vshaderTxt); | 2999 uTexCoordXform.appendDecl(this->ctxInfo(), &vshaderTxt); |
2777 vshaderTxt.append(";"); | 3000 vshaderTxt.append(";"); |
2778 uPosXform.appendDecl(this->ctxInfo(), &vshaderTxt); | 3001 uPosXform.appendDecl(this->ctxInfo(), &vshaderTxt); |
2779 vshaderTxt.append(";"); | 3002 vshaderTxt.append(";"); |
2780 vTexCoord.appendDecl(this->ctxInfo(), &vshaderTxt); | 3003 vTexCoord.appendDecl(this->ctxInfo(), &vshaderTxt); |
2781 vshaderTxt.append(";"); | 3004 vshaderTxt.append(";"); |
2782 | 3005 |
2783 vshaderTxt.append( | 3006 vshaderTxt.append( |
2784 "// Copy Program VS\n" | 3007 "// Copy Program VS\n" |
2785 "void main() {" | 3008 "void main() {" |
2786 " v_texCoord = a_vertex.xy * u_texCoordXform.xy + u_texCoordXform.zw;" | 3009 " v_texCoord = a_vertex.xy * u_texCoordXform.xy + u_texCoordXform.zw;" |
2787 " gl_Position.xy = a_vertex * u_posXform.xy + u_posXform.zw;" | 3010 " gl_Position.xy = a_vertex * u_posXform.xy + u_posXform.zw;" |
2788 " gl_Position.zw = vec2(0, 1);" | 3011 " gl_Position.zw = vec2(0, 1);" |
2789 "}" | 3012 "}" |
2790 ); | 3013 ); |
2791 | 3014 |
2792 SkString fshaderTxt(version); | 3015 SkString fshaderTxt(version); |
(...skipping 13 matching lines...) Expand all Loading... | |
2806 fsOutName = "gl_FragColor"; | 3029 fsOutName = "gl_FragColor"; |
2807 } | 3030 } |
2808 fshaderTxt.appendf( | 3031 fshaderTxt.appendf( |
2809 "// Copy Program FS\n" | 3032 "// Copy Program FS\n" |
2810 "void main() {" | 3033 "void main() {" |
2811 " %s = %s(u_texture, v_texCoord);" | 3034 " %s = %s(u_texture, v_texCoord);" |
2812 "}", | 3035 "}", |
2813 fsOutName, | 3036 fsOutName, |
2814 GrGLSLTexture2DFunctionName(kVec2f_GrSLType, this->glslGeneration()) | 3037 GrGLSLTexture2DFunctionName(kVec2f_GrSLType, this->glslGeneration()) |
2815 ); | 3038 ); |
2816 | 3039 |
2817 GL_CALL_RET(fCopyProgram.fProgram, CreateProgram()); | 3040 GL_CALL_RET(fCopyProgram.fProgram, CreateProgram()); |
2818 const char* str; | 3041 const char* str; |
2819 GrGLint length; | 3042 GrGLint length; |
2820 | 3043 |
2821 str = vshaderTxt.c_str(); | 3044 str = vshaderTxt.c_str(); |
2822 length = SkToInt(vshaderTxt.size()); | 3045 length = SkToInt(vshaderTxt.size()); |
2823 GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fCopyProgram.fPro gram, | 3046 GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fCopyProgram.fPro gram, |
2824 GR_GL_VERTEX_SHADER, &str, &le ngth, 1, &fStats); | 3047 GR_GL_VERTEX_SHADER, &str, &le ngth, 1, &fStats); |
2825 | 3048 |
2826 str = fshaderTxt.c_str(); | 3049 str = fshaderTxt.c_str(); |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3144 this->setVertexArrayID(gpu, 0); | 3367 this->setVertexArrayID(gpu, 0); |
3145 } | 3368 } |
3146 int attrCount = gpu->glCaps().maxVertexAttributes(); | 3369 int attrCount = gpu->glCaps().maxVertexAttributes(); |
3147 if (fDefaultVertexArrayAttribState.count() != attrCount) { | 3370 if (fDefaultVertexArrayAttribState.count() != attrCount) { |
3148 fDefaultVertexArrayAttribState.resize(attrCount); | 3371 fDefaultVertexArrayAttribState.resize(attrCount); |
3149 } | 3372 } |
3150 attribState = &fDefaultVertexArrayAttribState; | 3373 attribState = &fDefaultVertexArrayAttribState; |
3151 } | 3374 } |
3152 return attribState; | 3375 return attribState; |
3153 } | 3376 } |
OLD | NEW |