blob: 67ce62913ea9312e11dd7782b72c131e7f9ffe19 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
bsalomon@google.com669fdc42011-04-05 17:08:27 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
bsalomon@google.com669fdc42011-04-05 17:08:27 +00007 */
8
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
bsalomon@google.com669fdc42011-04-05 17:08:27 +000010#include "GrTexture.h"
bsalomon@google.comaa5b6732011-07-29 15:13:20 +000011
bsalomon@google.com669fdc42011-04-05 17:08:27 +000012#include "GrContext.h"
bsalomon@google.com05ef5102011-05-02 21:14:59 +000013#include "GrGpu.h"
bsalomon@google.comaa5b6732011-07-29 15:13:20 +000014#include "GrRenderTarget.h"
robertphillips@google.coma1e57952012-06-04 20:05:28 +000015#include "GrResourceCache.h"
bsalomon@google.com8295dc12011-05-02 12:53:34 +000016
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000017SK_DEFINE_INST_COUNT(GrTexture)
18
bsalomon@google.com669fdc42011-04-05 17:08:27 +000019bool GrTexture::readPixels(int left, int top, int width, int height,
bsalomon@google.com6f379512011-11-16 20:36:03 +000020 GrPixelConfig config, void* buffer,
21 size_t rowBytes) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +000022 // go through context so that all necessary flushing occurs
bsalomon@google.com6f379512011-11-16 20:36:03 +000023 GrContext* context = this->getContext();
24 if (NULL == context) {
25 return false;
26 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +000027 return context->readTexturePixels(this,
bsalomon@google.com6f379512011-11-16 20:36:03 +000028 left, top,
29 width, height,
30 config, buffer, rowBytes);
31}
32
33void GrTexture::writePixels(int left, int top, int width, int height,
34 GrPixelConfig config, const void* buffer,
35 size_t rowBytes) {
36 // go through context so that all necessary flushing occurs
37 GrContext* context = this->getContext();
38 if (NULL == context) {
39 return;
40 }
41 context->writeTexturePixels(this,
42 left, top,
43 width, height,
44 config, buffer, rowBytes);
bsalomon@google.com669fdc42011-04-05 17:08:27 +000045}
bsalomon@google.comcee661a2011-07-26 12:32:36 +000046
bsalomon@google.comaa5b6732011-07-29 15:13:20 +000047void GrTexture::releaseRenderTarget() {
48 if (NULL != fRenderTarget) {
49 GrAssert(fRenderTarget->asTexture() == this);
robertphillips@google.com32716282012-06-04 12:48:45 +000050 GrAssert(fDesc.fFlags & kRenderTarget_GrTextureFlagBit);
51
bsalomon@google.comaa5b6732011-07-29 15:13:20 +000052 fRenderTarget->onTextureReleaseRenderTarget();
53 fRenderTarget->unref();
54 fRenderTarget = NULL;
robertphillips@google.com32716282012-06-04 12:48:45 +000055
56 fDesc.fFlags = fDesc.fFlags &
57 ~(kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit);
58 fDesc.fSampleCnt = 0;
bsalomon@google.comaa5b6732011-07-29 15:13:20 +000059 }
60}
61
62void GrTexture::onAbandon() {
63 if (NULL != fRenderTarget) {
64 fRenderTarget->abandon();
65 }
66}
67
robertphillips@google.com32716282012-06-04 12:48:45 +000068void GrTexture::validateDesc() const {
69 if (NULL != this->asRenderTarget()) {
70 // This texture has a render target
71 GrAssert(0 != (fDesc.fFlags & kRenderTarget_GrTextureFlagBit));
72
73 if (NULL != this->asRenderTarget()->getStencilBuffer()) {
74 GrAssert(0 != (fDesc.fFlags & kNoStencil_GrTextureFlagBit));
75 } else {
76 GrAssert(0 == (fDesc.fFlags & kNoStencil_GrTextureFlagBit));
77 }
78
79 GrAssert(fDesc.fSampleCnt == this->asRenderTarget()->numSamples());
80 } else {
81 GrAssert(0 == (fDesc.fFlags & kRenderTarget_GrTextureFlagBit));
82 GrAssert(0 == (fDesc.fFlags & kNoStencil_GrTextureFlagBit));
83 GrAssert(0 == fDesc.fSampleCnt);
84 }
85}
robertphillips@google.coma1e57952012-06-04 20:05:28 +000086
87enum TextureBits {
88 kFirst_TextureBit = (GrResourceKey::kLastPublic_TypeBit << 1),
89
90 /*
91 * The kNPOT bit is set when the texture is NPOT and is being repeated
92 * but the hardware doesn't support that feature.
93 */
94 kNPOT_TextureBit = kFirst_TextureBit,
95 /*
96 * The kFilter bit can only be set when the kNPOT flag is set and indicates
97 * whether the resizing of the texture should use filtering. This is
98 * to handle cases where the original texture is indexed to disable
99 * filtering.
100 */
101 kFilter_TextureBit = kNPOT_TextureBit << 1,
102 /*
103 * The kScratch bit is set if the texture is being used as a scratch
104 * texture.
105 */
106 kScratch_TextureBit = kFilter_TextureBit << 1,
107};
108
109namespace {
110void gen_texture_key_values(const GrGpu* gpu,
111 const GrSamplerState* sampler,
robertphillips@google.coma1e57952012-06-04 20:05:28 +0000112 const GrTextureDesc& desc,
113 bool scratch,
114 uint32_t v[4]) {
robertphillips@google.com75b3c962012-06-07 12:08:45 +0000115
116 uint64_t clientKey = desc.fClientCacheID;
robertphillips@google.coma1e57952012-06-04 20:05:28 +0000117
118 if (scratch) {
119 // Instead of a client-provided key of the texture contents
120 // we create a key of from the descriptor.
robertphillips@google.com75b3c962012-06-07 12:08:45 +0000121 GrAssert(kScratch_CacheID == clientKey);
robertphillips@google.coma1e57952012-06-04 20:05:28 +0000122 clientKey = (desc.fFlags << 8) | ((uint64_t) desc.fConfig << 32);
123 }
124
125 // we assume we only need 16 bits of width and height
126 // assert that texture creation will fail anyway if this assumption
127 // would cause key collisions.
128 GrAssert(gpu->getCaps().fMaxTextureSize <= SK_MaxU16);
caryclark@google.comcf6285b2012-06-06 12:09:01 +0000129 v[0] = (uint32_t) (clientKey & 0xffffffffUL);
130 v[1] = (uint32_t) ((clientKey >> 32) & 0xffffffffUL);
robertphillips@google.coma1e57952012-06-04 20:05:28 +0000131 v[2] = desc.fWidth | (desc.fHeight << 16);
132
133 v[3] = (desc.fSampleCnt << 24);
134 GrAssert(desc.fSampleCnt >= 0 && desc.fSampleCnt < 256);
135
136 if (!gpu->getCaps().fNPOTTextureTileSupport) {
137 bool isPow2 = GrIsPow2(desc.fWidth) && GrIsPow2(desc.fHeight);
138
139 bool tiled = NULL != sampler &&
140 ((sampler->getWrapX() != GrSamplerState::kClamp_WrapMode) ||
141 (sampler->getWrapY() != GrSamplerState::kClamp_WrapMode));
142
143 if (tiled && !isPow2) {
144 v[3] |= kNPOT_TextureBit;
145 if (GrSamplerState::kNearest_Filter != sampler->getFilter()) {
146 v[3] |= kFilter_TextureBit;
147 }
148 }
149 }
150
151 if (scratch) {
152 v[3] |= kScratch_TextureBit;
153 }
154
155 v[3] |= GrResourceKey::kTexture_TypeBit;
156}
157}
158
159GrResourceKey GrTexture::ComputeKey(const GrGpu* gpu,
160 const GrSamplerState* sampler,
robertphillips@google.coma1e57952012-06-04 20:05:28 +0000161 const GrTextureDesc& desc,
162 bool scratch) {
163 uint32_t v[4];
robertphillips@google.com75b3c962012-06-07 12:08:45 +0000164 gen_texture_key_values(gpu, sampler, desc, scratch, v);
robertphillips@google.coma1e57952012-06-04 20:05:28 +0000165 return GrResourceKey(v);
166}
167
168bool GrTexture::NeedsResizing(const GrResourceKey& key) {
169 return 0 != (key.getValue32(3) & kNPOT_TextureBit);
170}
171
172bool GrTexture::IsScratchTexture(const GrResourceKey& key) {
173 return 0 != (key.getValue32(3) & kScratch_TextureBit);
174}
175
176bool GrTexture::NeedsFiltering(const GrResourceKey& key) {
177 return 0 != (key.getValue32(3) & kFilter_TextureBit);
178}