blob: 4f4c5f5850ffde54bcda94b173d32e5f0e52c84c [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
bsalomon@google.com669fdc42011-04-05 17:08:27 +000017bool GrTexture::readPixels(int left, int top, int width, int height,
bsalomon@google.com6f379512011-11-16 20:36:03 +000018 GrPixelConfig config, void* buffer,
19 size_t rowBytes) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +000020 // go through context so that all necessary flushing occurs
bsalomon@google.com6f379512011-11-16 20:36:03 +000021 GrContext* context = this->getContext();
22 if (NULL == context) {
23 return false;
24 }
bsalomon@google.com669fdc42011-04-05 17:08:27 +000025 return context->readTexturePixels(this,
bsalomon@google.com6f379512011-11-16 20:36:03 +000026 left, top,
27 width, height,
28 config, buffer, rowBytes);
29}
30
31void GrTexture::writePixels(int left, int top, int width, int height,
32 GrPixelConfig config, const void* buffer,
33 size_t rowBytes) {
34 // go through context so that all necessary flushing occurs
35 GrContext* context = this->getContext();
36 if (NULL == context) {
37 return;
38 }
39 context->writeTexturePixels(this,
40 left, top,
41 width, height,
42 config, buffer, rowBytes);
bsalomon@google.com669fdc42011-04-05 17:08:27 +000043}
bsalomon@google.comcee661a2011-07-26 12:32:36 +000044
bsalomon@google.comaa5b6732011-07-29 15:13:20 +000045void GrTexture::releaseRenderTarget() {
46 if (NULL != fRenderTarget) {
47 GrAssert(fRenderTarget->asTexture() == this);
robertphillips@google.com32716282012-06-04 12:48:45 +000048 GrAssert(fDesc.fFlags & kRenderTarget_GrTextureFlagBit);
49
bsalomon@google.comaa5b6732011-07-29 15:13:20 +000050 fRenderTarget->onTextureReleaseRenderTarget();
51 fRenderTarget->unref();
52 fRenderTarget = NULL;
robertphillips@google.com32716282012-06-04 12:48:45 +000053
54 fDesc.fFlags = fDesc.fFlags &
55 ~(kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit);
56 fDesc.fSampleCnt = 0;
bsalomon@google.comaa5b6732011-07-29 15:13:20 +000057 }
58}
59
60void GrTexture::onAbandon() {
61 if (NULL != fRenderTarget) {
62 fRenderTarget->abandon();
63 }
64}
65
robertphillips@google.com32716282012-06-04 12:48:45 +000066void GrTexture::validateDesc() const {
67 if (NULL != this->asRenderTarget()) {
68 // This texture has a render target
69 GrAssert(0 != (fDesc.fFlags & kRenderTarget_GrTextureFlagBit));
70
71 if (NULL != this->asRenderTarget()->getStencilBuffer()) {
72 GrAssert(0 != (fDesc.fFlags & kNoStencil_GrTextureFlagBit));
73 } else {
74 GrAssert(0 == (fDesc.fFlags & kNoStencil_GrTextureFlagBit));
75 }
76
77 GrAssert(fDesc.fSampleCnt == this->asRenderTarget()->numSamples());
78 } else {
79 GrAssert(0 == (fDesc.fFlags & kRenderTarget_GrTextureFlagBit));
80 GrAssert(0 == (fDesc.fFlags & kNoStencil_GrTextureFlagBit));
81 GrAssert(0 == fDesc.fSampleCnt);
82 }
83}
robertphillips@google.coma1e57952012-06-04 20:05:28 +000084
85enum TextureBits {
86 kFirst_TextureBit = (GrResourceKey::kLastPublic_TypeBit << 1),
87
88 /*
89 * The kNPOT bit is set when the texture is NPOT and is being repeated
90 * but the hardware doesn't support that feature.
91 */
92 kNPOT_TextureBit = kFirst_TextureBit,
93 /*
94 * The kFilter bit can only be set when the kNPOT flag is set and indicates
95 * whether the resizing of the texture should use filtering. This is
96 * to handle cases where the original texture is indexed to disable
97 * filtering.
98 */
99 kFilter_TextureBit = kNPOT_TextureBit << 1,
100 /*
101 * The kScratch bit is set if the texture is being used as a scratch
102 * texture.
103 */
104 kScratch_TextureBit = kFilter_TextureBit << 1,
105};
106
107namespace {
108void gen_texture_key_values(const GrGpu* gpu,
109 const GrSamplerState* sampler,
robertphillips@google.coma1e57952012-06-04 20:05:28 +0000110 const GrTextureDesc& desc,
111 bool scratch,
112 uint32_t v[4]) {
robertphillips@google.com75b3c962012-06-07 12:08:45 +0000113
114 uint64_t clientKey = desc.fClientCacheID;
robertphillips@google.coma1e57952012-06-04 20:05:28 +0000115
116 if (scratch) {
117 // Instead of a client-provided key of the texture contents
118 // we create a key of from the descriptor.
robertphillips@google.com75b3c962012-06-07 12:08:45 +0000119 GrAssert(kScratch_CacheID == clientKey);
robertphillips@google.coma1e57952012-06-04 20:05:28 +0000120 clientKey = (desc.fFlags << 8) | ((uint64_t) desc.fConfig << 32);
121 }
122
123 // we assume we only need 16 bits of width and height
124 // assert that texture creation will fail anyway if this assumption
125 // would cause key collisions.
126 GrAssert(gpu->getCaps().fMaxTextureSize <= SK_MaxU16);
caryclark@google.comcf6285b2012-06-06 12:09:01 +0000127 v[0] = (uint32_t) (clientKey & 0xffffffffUL);
128 v[1] = (uint32_t) ((clientKey >> 32) & 0xffffffffUL);
robertphillips@google.coma1e57952012-06-04 20:05:28 +0000129 v[2] = desc.fWidth | (desc.fHeight << 16);
130
131 v[3] = (desc.fSampleCnt << 24);
132 GrAssert(desc.fSampleCnt >= 0 && desc.fSampleCnt < 256);
133
134 if (!gpu->getCaps().fNPOTTextureTileSupport) {
135 bool isPow2 = GrIsPow2(desc.fWidth) && GrIsPow2(desc.fHeight);
136
137 bool tiled = NULL != sampler &&
138 ((sampler->getWrapX() != GrSamplerState::kClamp_WrapMode) ||
139 (sampler->getWrapY() != GrSamplerState::kClamp_WrapMode));
140
141 if (tiled && !isPow2) {
142 v[3] |= kNPOT_TextureBit;
143 if (GrSamplerState::kNearest_Filter != sampler->getFilter()) {
144 v[3] |= kFilter_TextureBit;
145 }
146 }
147 }
148
149 if (scratch) {
150 v[3] |= kScratch_TextureBit;
151 }
152
153 v[3] |= GrResourceKey::kTexture_TypeBit;
154}
155}
156
157GrResourceKey GrTexture::ComputeKey(const GrGpu* gpu,
158 const GrSamplerState* sampler,
robertphillips@google.coma1e57952012-06-04 20:05:28 +0000159 const GrTextureDesc& desc,
160 bool scratch) {
161 uint32_t v[4];
robertphillips@google.com75b3c962012-06-07 12:08:45 +0000162 gen_texture_key_values(gpu, sampler, desc, scratch, v);
robertphillips@google.coma1e57952012-06-04 20:05:28 +0000163 return GrResourceKey(v);
164}
165
166bool GrTexture::NeedsResizing(const GrResourceKey& key) {
167 return 0 != (key.getValue32(3) & kNPOT_TextureBit);
168}
169
170bool GrTexture::IsScratchTexture(const GrResourceKey& key) {
171 return 0 != (key.getValue32(3) & kScratch_TextureBit);
172}
173
174bool GrTexture::NeedsFiltering(const GrResourceKey& key) {
175 return 0 != (key.getValue32(3) & kFilter_TextureBit);
176}