180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc.
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrTexture.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrContext.h"
137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "GrDrawTargetCaps.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrGpu.h"
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrRenderTarget.h"
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrResourceCache.h"
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_DEFINE_INST_COUNT(GrTexture)
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerGrTexture::~GrTexture() {
217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (NULL != fRenderTarget.get()) {
227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        fRenderTarget.get()->owningTextureDestroyed();
237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/**
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * This method allows us to interrupt the normal deletion process and place
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * textures back in the texture cache when their ref count goes to zero.
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrTexture::internal_dispose() const {
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (this->isSetFlag((GrTextureFlags) kReturnToCache_FlagBit) &&
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL != this->INHERITED::getContext()) {
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrTexture* nonConstThis = const_cast<GrTexture *>(this);
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->fRefCnt = 1;      // restore ref count to initial setting
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        nonConstThis->resetFlag((GrTextureFlags) kReturnToCache_FlagBit);
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        nonConstThis->INHERITED::getContext()->addExistingTextureToCache(nonConstThis);
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Note: "this" texture might be freed inside addExistingTextureToCache
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // if it is purged.
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->INHERITED::internal_dispose();
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool GrTexture::readPixels(int left, int top, int width, int height,
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           GrPixelConfig config, void* buffer,
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           size_t rowBytes, uint32_t pixelOpsFlags) {
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // go through context so that all necessary flushing occurs
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrContext* context = this->getContext();
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == context) {
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return context->readTexturePixels(this,
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      left, top, width, height,
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      config, buffer, rowBytes,
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      pixelOpsFlags);
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrTexture::writePixels(int left, int top, int width, int height,
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            GrPixelConfig config, const void* buffer,
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            size_t rowBytes, uint32_t pixelOpsFlags) {
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // go through context so that all necessary flushing occurs
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrContext* context = this->getContext();
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == context) {
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    context->writeTexturePixels(this,
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                left, top, width, height,
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                config, buffer, rowBytes,
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                pixelOpsFlags);
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrTexture::onRelease() {
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrAssert(!this->isSetFlag((GrTextureFlags) kReturnToCache_FlagBit));
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    INHERITED::onRelease();
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrTexture::onAbandon() {
827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (NULL != fRenderTarget.get()) {
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fRenderTarget->abandon();
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    INHERITED::onAbandon();
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrTexture::validateDesc() const {
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != this->asRenderTarget()) {
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // This texture has a render target
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrAssert(0 != (fDesc.fFlags & kRenderTarget_GrTextureFlagBit));
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL != this->asRenderTarget()->getStencilBuffer()) {
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GrAssert(0 != (fDesc.fFlags & kNoStencil_GrTextureFlagBit));
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            GrAssert(0 == (fDesc.fFlags & kNoStencil_GrTextureFlagBit));
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrAssert(fDesc.fSampleCnt == this->asRenderTarget()->numSamples());
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrAssert(0 == (fDesc.fFlags & kRenderTarget_GrTextureFlagBit));
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrAssert(0 == (fDesc.fFlags & kNoStencil_GrTextureFlagBit));
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        GrAssert(0 == fDesc.fSampleCnt);
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
107d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger// These flags need to fit in a GrResourceKey::ResourceFlags so they can be folded into the texture
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// key
109d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergerenum TextureFlags {
110d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    /**
111d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     * The kStretchToPOT bit is set when the texture is NPOT and is being repeated but the
112d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger     * hardware doesn't support that feature.
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
114d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    kStretchToPOT_TextureFlag = 0x1,
115d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    /**
11658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger     * The kBilerp bit can only be set when the kStretchToPOT flag is set and indicates whether the
11758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger     * stretched texture should be bilerped.
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
11958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger     kBilerp_TextureFlag       = 0x2,
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querunamespace {
123d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek SollenbergerGrResourceKey::ResourceFlags get_texture_flags(const GrGpu* gpu,
124d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                               const GrTextureParams* params,
125d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                               const GrTextureDesc& desc) {
126d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrResourceKey::ResourceFlags flags = 0;
127d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    bool tiled = NULL != params && params->isTiled();
1287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (tiled && !gpu->caps()->npotTextureTileSupport()) {
129d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        if (!GrIsPow2(desc.fWidth) || !GrIsPow2(desc.fHeight)) {
130d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger            flags |= kStretchToPOT_TextureFlag;
13158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger            switch(params->filterMode()) {
13258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                case GrTextureParams::kNone_FilterMode:
13358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                    break;
13458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                case GrTextureParams::kBilerp_FilterMode:
13558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                case GrTextureParams::kMipMap_FilterMode:
13658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                    flags |= kBilerp_TextureFlag;
13758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger                    break;
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
141d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    return flags;
142d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger}
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
144d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek SollenbergerGrResourceKey::ResourceType texture_resource_type() {
145d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    static const GrResourceKey::ResourceType gType = GrResourceKey::GenerateResourceType();
146d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    return gType;
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
148096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
149096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger// FIXME:  This should be refactored with the code in gl/GrGpuGL.cpp.
150096defe64d408e54474fe19f418c95bf1a554fc7Derek SollenbergerGrSurfaceOrigin resolve_origin(const GrTextureDesc& desc) {
151096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    // By default, GrRenderTargets are GL's normal orientation so that they
152096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    // can be drawn to by the outside world without the client having
153096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    // to render upside down.
154096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
155096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    if (kDefault_GrSurfaceOrigin == desc.fOrigin) {
156096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        return renderTarget ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin;
157096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    } else {
158096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        return desc.fOrigin;
159096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    }
160096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger}
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrResourceKey GrTexture::ComputeKey(const GrGpu* gpu,
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    const GrTextureParams* params,
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                    const GrTextureDesc& desc,
166d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger                                    const GrCacheID& cacheID) {
167d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrResourceKey::ResourceFlags flags = get_texture_flags(gpu, params, desc);
168d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    return GrResourceKey(cacheID, texture_resource_type(), flags);
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
171d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek SollenbergerGrResourceKey GrTexture::ComputeScratchKey(const GrTextureDesc& desc) {
172d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrCacheID::Key idKey;
173d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    // Instead of a client-provided key of the texture contents we create a key from the
174d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    // descriptor.
175096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    GR_STATIC_ASSERT(sizeof(idKey) >= 16);
176d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrAssert(desc.fHeight < (1 << 16));
177d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrAssert(desc.fWidth < (1 << 16));
178d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    idKey.fData32[0] = (desc.fWidth) | (desc.fHeight << 16);
179d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    idKey.fData32[1] = desc.fConfig | desc.fSampleCnt << 16;
180d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    idKey.fData32[2] = desc.fFlags;
181096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    idKey.fData32[3] = resolve_origin(desc);    // Only needs 2 bits actually
182096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    static const int kPadSize = sizeof(idKey) - 16;
183096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    GR_STATIC_ASSERT(kPadSize >= 0);
184096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    memset(idKey.fData8 + 16, 0, kPadSize);
185d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
186d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    GrCacheID cacheID(GrResourceKey::ScratchDomain(), idKey);
187d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    return GrResourceKey(cacheID, texture_resource_type(), 0);
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
190d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergerbool GrTexture::NeedsResizing(const GrResourceKey& key) {
191d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    return SkToBool(key.getResourceFlags() & kStretchToPOT_TextureFlag);
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerbool GrTexture::NeedsBilerp(const GrResourceKey& key) {
19558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    return SkToBool(key.getResourceFlags() & kBilerp_TextureFlag);
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
197