GrTexture.cpp revision a1e5795279bd085496fa04c59e588f440bf30457
1669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com */
8669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
10669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com#include "GrTexture.h"
11aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com
12669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com#include "GrContext.h"
1305ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.com#include "GrGpu.h"
14aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com#include "GrRenderTarget.h"
15a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com#include "GrResourceCache.h"
168295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com
17669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.combool GrTexture::readPixels(int left, int top, int width, int height,
186f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                           GrPixelConfig config, void* buffer,
196f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                           size_t rowBytes) {
20669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    // go through context so that all necessary flushing occurs
216f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    GrContext* context = this->getContext();
226f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (NULL == context) {
236f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        return false;
246f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
25669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    return context->readTexturePixels(this,
266f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                      left, top,
276f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                      width, height,
286f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                      config, buffer, rowBytes);
296f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com}
306f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
316f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.comvoid GrTexture::writePixels(int left, int top, int width, int height,
326f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                            GrPixelConfig config, const void* buffer,
336f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                            size_t rowBytes) {
346f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    // go through context so that all necessary flushing occurs
356f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    GrContext* context = this->getContext();
366f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (NULL == context) {
376f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        return;
386f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
396f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    context->writeTexturePixels(this,
406f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                left, top,
416f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                width, height,
426f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com                                config, buffer, rowBytes);
43669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com}
44cee661af926cc977addc6e039b7022975a448acebsalomon@google.com
45aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.comvoid GrTexture::releaseRenderTarget() {
46aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com    if (NULL != fRenderTarget) {
47aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com        GrAssert(fRenderTarget->asTexture() == this);
4832716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com        GrAssert(fDesc.fFlags & kRenderTarget_GrTextureFlagBit);
4932716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com
50aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com        fRenderTarget->onTextureReleaseRenderTarget();
51aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com        fRenderTarget->unref();
52aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com        fRenderTarget = NULL;
5332716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com
5432716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com        fDesc.fFlags = fDesc.fFlags &
5532716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com            ~(kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit);
5632716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com        fDesc.fSampleCnt = 0;
57aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com    }
58aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com}
59aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com
60aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.comvoid GrTexture::onAbandon() {
61aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com    if (NULL != fRenderTarget) {
62aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com        fRenderTarget->abandon();
63aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com    }
64aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com}
65aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com
6632716283420df90644c8b8114308f7967aa91d9frobertphillips@google.comvoid GrTexture::validateDesc() const {
6732716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com    if (NULL != this->asRenderTarget()) {
6832716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com        // This texture has a render target
6932716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com        GrAssert(0 != (fDesc.fFlags & kRenderTarget_GrTextureFlagBit));
7032716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com
7132716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com        if (NULL != this->asRenderTarget()->getStencilBuffer()) {
7232716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com            GrAssert(0 != (fDesc.fFlags & kNoStencil_GrTextureFlagBit));
7332716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com        } else {
7432716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com            GrAssert(0 == (fDesc.fFlags & kNoStencil_GrTextureFlagBit));
7532716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com        }
7632716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com
7732716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com        GrAssert(fDesc.fSampleCnt == this->asRenderTarget()->numSamples());
7832716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com    } else {
7932716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com        GrAssert(0 == (fDesc.fFlags & kRenderTarget_GrTextureFlagBit));
8032716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com        GrAssert(0 == (fDesc.fFlags & kNoStencil_GrTextureFlagBit));
8132716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com        GrAssert(0 == fDesc.fSampleCnt);
8232716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com    }
8332716283420df90644c8b8114308f7967aa91d9frobertphillips@google.com}
84a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com
85a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.comenum TextureBits {
86a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    kFirst_TextureBit = (GrResourceKey::kLastPublic_TypeBit << 1),
87a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com
88a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    /*
89a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com     * The kNPOT bit is set when the texture is NPOT and is being repeated
90a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com     * but the hardware doesn't support that feature.
91a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com     */
92a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    kNPOT_TextureBit            = kFirst_TextureBit,
93a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    /*
94a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com     * The kFilter bit can only be set when the kNPOT flag is set and indicates
95a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com     * whether the resizing of the texture should use filtering. This is
96a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com     * to handle cases where the original texture is indexed to disable
97a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com     * filtering.
98a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com     */
99a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    kFilter_TextureBit          = kNPOT_TextureBit << 1,
100a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    /*
101a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com     * The kScratch bit is set if the texture is being used as a scratch
102a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com     * texture.
103a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com     */
104a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    kScratch_TextureBit         = kFilter_TextureBit << 1,
105a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com};
106a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com
107a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.comnamespace {
108a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.comvoid gen_texture_key_values(const GrGpu* gpu,
109a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com                            const GrSamplerState* sampler,
110a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com                            GrTexture::TextureKey clientKey,
111a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com                            const GrTextureDesc& desc,
112a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com                            bool scratch,
113a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com                            uint32_t v[4]) {
114a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    GR_STATIC_ASSERT(sizeof(GrTexture::TextureKey) == sizeof(uint64_t));
115a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com
116a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    if (scratch) {
117a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com        // Instead of a client-provided key of the texture contents
118a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com        // we create a key of from the descriptor.
119a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com        GrAssert(0 == clientKey);
120a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com        clientKey = (desc.fFlags << 8) | ((uint64_t) desc.fConfig << 32);
121a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    }
122a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com
123a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    // we assume we only need 16 bits of width and height
124a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    // assert that texture creation will fail anyway if this assumption
125a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    // would cause key collisions.
126a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    GrAssert(gpu->getCaps().fMaxTextureSize <= SK_MaxU16);
127a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    v[0] = clientKey & 0xffffffffUL;
128a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    v[1] = (clientKey >> 32) & 0xffffffffUL;
129a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    v[2] = desc.fWidth | (desc.fHeight << 16);
130a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com
131a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    v[3] = (desc.fSampleCnt << 24);
132a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    GrAssert(desc.fSampleCnt >= 0 && desc.fSampleCnt < 256);
133a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com
134a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    if (!gpu->getCaps().fNPOTTextureTileSupport) {
135a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com        bool isPow2 = GrIsPow2(desc.fWidth) && GrIsPow2(desc.fHeight);
136a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com
137a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com        bool tiled = NULL != sampler &&
138a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com                   ((sampler->getWrapX() != GrSamplerState::kClamp_WrapMode) ||
139a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com                    (sampler->getWrapY() != GrSamplerState::kClamp_WrapMode));
140a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com
141a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com        if (tiled && !isPow2) {
142a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com            v[3] |= kNPOT_TextureBit;
143a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com            if (GrSamplerState::kNearest_Filter != sampler->getFilter()) {
144a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com                v[3] |= kFilter_TextureBit;
145a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com            }
146a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com        }
147a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    }
148a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com
149a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    if (scratch) {
150a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com        v[3] |= kScratch_TextureBit;
151a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    }
152a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com
153a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    v[3] |= GrResourceKey::kTexture_TypeBit;
154a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com}
155a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com}
156a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com
157a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.comGrResourceKey GrTexture::ComputeKey(const GrGpu* gpu,
158a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com                                    const GrSamplerState* sampler,
159a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com                                    TextureKey clientKey,
160a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com                                    const GrTextureDesc& desc,
161a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com                                    bool scratch) {
162a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    uint32_t v[4];
163a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    gen_texture_key_values(gpu, sampler, clientKey, desc, scratch, v);
164a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    return GrResourceKey(v);
165a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com}
166a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com
167a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.combool GrTexture::NeedsResizing(const GrResourceKey& key) {
168a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    return 0 != (key.getValue32(3) & kNPOT_TextureBit);
169a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com}
170a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com
171a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.combool GrTexture::IsScratchTexture(const GrResourceKey& key) {
172a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    return 0 != (key.getValue32(3) & kScratch_TextureBit);
173a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com}
174a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com
175a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.combool GrTexture::NeedsFiltering(const GrResourceKey& key) {
176a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    return 0 != (key.getValue32(3) & kFilter_TextureBit);
177a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com}
178