diff options
author | fmalita <fmalita@chromium.org> | 2015-01-31 07:02:18 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-01-31 07:02:18 -0800 |
commit | 6bfef2dfec3253efa48aec0b5ea108e0dc041d15 (patch) | |
tree | 7402cf0046bfa6077cb3e732e57e63f2f7927f63 /src/gpu/GrContext.cpp | |
parent | 6726e78cd971e7dce42f8b5904284f744f55cb36 (diff) |
Revert of Move npot resizing out of GrContext and simplify GrContext texture functions. (patchset #9 id:160001 of https://codereview.chromium.org/882223003/)
Reason for revert:
webGL conformance failures:
WebglConformance.conformance_textures_tex_image_and_sub_image_2d_with_video
WebglConformance.conformance_textures_texture_npot_video
https://codereview.chromium.org/892773003/
http://build.chromium.org/p/tryserver.chromium.mac/builders/mac_chromium_rel_ng/builds/29272
Original issue's description:
> Move npot resizing out of GrContext and simplify GrContext texture functions.
>
> Committed: https://skia.googlesource.com/skia/+/8a8100349105c8c6de39fcb34e47679da7a67f54
TBR=robertphillips@google.com,bsalomon@google.com
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
Review URL: https://codereview.chromium.org/868233005
Diffstat (limited to 'src/gpu/GrContext.cpp')
-rwxr-xr-x | src/gpu/GrContext.cpp | 275 |
1 files changed, 243 insertions, 32 deletions
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 07073a5ee5..13b0bfaec5 100755 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -223,9 +223,219 @@ GrTextContext* GrContext::createTextContext(GrRenderTarget* renderTarget, //////////////////////////////////////////////////////////////////////////////// -GrTexture* GrContext::createTexture(const GrSurfaceDesc& desc, const void* srcData, - size_t rowBytes) { - return fGpu->createTexture(desc, true, srcData, rowBytes); +static void stretch_image(void* dst, + int dstW, + int dstH, + const void* src, + int srcW, + int srcH, + size_t bpp) { + SkFixed dx = (srcW << 16) / dstW; + SkFixed dy = (srcH << 16) / dstH; + + SkFixed y = dy >> 1; + + size_t dstXLimit = dstW*bpp; + for (int j = 0; j < dstH; ++j) { + SkFixed x = dx >> 1; + const uint8_t* srcRow = reinterpret_cast<const uint8_t *>(src) + (y>>16)*srcW*bpp; + uint8_t* dstRow = reinterpret_cast<uint8_t *>(dst) + j*dstW*bpp; + for (size_t i = 0; i < dstXLimit; i += bpp) { + memcpy(dstRow + i, srcRow + (x>>16)*bpp, bpp); + x += dx; + } + y += dy; + } +} + +enum ResizeFlags { + /** + * The kStretchToPOT bit is set when the texture is NPOT and is being repeated or mipped but the + * hardware doesn't support that feature. + */ + kStretchToPOT_ResizeFlag = 0x1, + /** + * The kBilerp bit can only be set when the kStretchToPOT flag is set and indicates whether the + * stretched texture should be bilerped. + */ + kBilerp_ResizeFlag = 0x2, +}; + +static uint32_t get_texture_flags(const GrGpu* gpu, + const GrTextureParams* params, + const GrSurfaceDesc& desc) { + uint32_t flags = 0; + bool tiled = params && params->isTiled(); + if (tiled && !gpu->caps()->npotTextureTileSupport()) { + if (!SkIsPow2(desc.fWidth) || !SkIsPow2(desc.fHeight)) { + flags |= kStretchToPOT_ResizeFlag; + switch(params->filterMode()) { + case GrTextureParams::kNone_FilterMode: + break; + case GrTextureParams::kBilerp_FilterMode: + case GrTextureParams::kMipMap_FilterMode: + flags |= kBilerp_ResizeFlag; + break; + } + } + } + return flags; +} +// The desired texture is NPOT and tiled but that isn't supported by +// the current hardware. Resize the texture to be a POT +GrTexture* GrContext::createResizedTexture(const GrSurfaceDesc& desc, + const GrContentKey& origKey, + const void* srcData, + size_t rowBytes, + bool filter) { + SkAutoTUnref<GrTexture> clampedTexture(this->findAndRefTexture(desc, origKey, NULL)); + if (NULL == clampedTexture) { + clampedTexture.reset(this->createTexture(NULL, desc, origKey, srcData, rowBytes)); + + if (NULL == clampedTexture) { + return NULL; + } + clampedTexture->cacheAccess().setContentKey(origKey); + } + + GrSurfaceDesc rtDesc = desc; + rtDesc.fFlags = rtDesc.fFlags | + kRenderTarget_GrSurfaceFlag | + kNoStencil_GrSurfaceFlag; + rtDesc.fWidth = GrNextPow2(desc.fWidth); + rtDesc.fHeight = GrNextPow2(desc.fHeight); + + GrTexture* texture = fGpu->createTexture(rtDesc, true, NULL, 0); + + if (texture) { + GrPipelineBuilder pipelineBuilder; + pipelineBuilder.setRenderTarget(texture->asRenderTarget()); + + // if filtering is not desired then we want to ensure all + // texels in the resampled image are copies of texels from + // the original. + GrTextureParams params(SkShader::kClamp_TileMode, + filter ? GrTextureParams::kBilerp_FilterMode : + GrTextureParams::kNone_FilterMode); + pipelineBuilder.addColorTextureProcessor(clampedTexture, SkMatrix::I(), params); + + uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType | + GrDefaultGeoProcFactory::kLocalCoord_GPType; + SkAutoTUnref<const GrGeometryProcessor> gp( + GrDefaultGeoProcFactory::Create(flags, GrColor_WHITE)); + + GrDrawTarget::AutoReleaseGeometry arg(fDrawBuffer, 4, gp->getVertexStride(), 0); + SkASSERT(gp->getVertexStride() == 2 * sizeof(SkPoint)); + + if (arg.succeeded()) { + SkPoint* verts = (SkPoint*) arg.vertices(); + verts[0].setIRectFan(0, 0, texture->width(), texture->height(), 2 * sizeof(SkPoint)); + verts[1].setIRectFan(0, 0, 1, 1, 2 * sizeof(SkPoint)); + fDrawBuffer->drawNonIndexed(&pipelineBuilder, gp, kTriangleFan_GrPrimitiveType, 0, 4); + } else { + texture->unref(); + texture = NULL; + } + } else { + // TODO: Our CPU stretch doesn't filter. But we create separate + // stretched textures when the texture params is either filtered or + // not. Either implement filtered stretch blit on CPU or just create + // one when FBO case fails. + + rtDesc.fFlags = kNone_GrSurfaceFlags; + // no longer need to clamp at min RT size. + rtDesc.fWidth = GrNextPow2(desc.fWidth); + rtDesc.fHeight = GrNextPow2(desc.fHeight); + + // We shouldn't be resizing a compressed texture. + SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig)); + + size_t bpp = GrBytesPerPixel(desc.fConfig); + GrAutoMalloc<128*128*4> stretchedPixels(bpp * rtDesc.fWidth * rtDesc.fHeight); + stretch_image(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight, + srcData, desc.fWidth, desc.fHeight, bpp); + + size_t stretchedRowBytes = rtDesc.fWidth * bpp; + + texture = fGpu->createTexture(rtDesc, true, stretchedPixels.get(), stretchedRowBytes); + SkASSERT(texture); + } + + return texture; +} + +static GrContentKey::Domain ResizeDomain() { + static const GrContentKey::Domain kDomain = GrContentKey::GenerateDomain(); + return kDomain; +} + +GrTexture* GrContext::createTexture(const GrTextureParams* params, + const GrSurfaceDesc& desc, + const GrContentKey& origKey, + const void* srcData, + size_t rowBytes, + GrContentKey* outKey) { + GrTexture* texture; + uint32_t flags = get_texture_flags(fGpu, params, desc); + SkTCopyOnFirstWrite<GrContentKey> key(origKey); + if (flags) { + // We don't have a code path to resize compressed textures. + if (GrPixelConfigIsCompressed(desc.fConfig)) { + return NULL; + } + texture = this->createResizedTexture(desc, origKey, srcData, rowBytes, + SkToBool(flags & kBilerp_ResizeFlag)); + + GrContentKey::Builder builder(key.writable(), origKey, ResizeDomain(), 1); + builder[0] = flags; + + } else { + texture = fGpu->createTexture(desc, true, srcData, rowBytes); + } + + if (texture) { + if (texture->cacheAccess().setContentKey(*key)) { + if (outKey) { + *outKey = *key; + } + } else { + texture->unref(); + texture = NULL; + } + } + + return texture; +} + +GrTexture* GrContext::findAndRefTexture(const GrSurfaceDesc& desc, + const GrContentKey& origKey, + const GrTextureParams* params) { + uint32_t flags = get_texture_flags(fGpu, params, desc); + SkTCopyOnFirstWrite<GrContentKey> key(origKey); + if (flags) { + GrContentKey::Builder builder(key.writable(), origKey, ResizeDomain(), 1); + builder[0] = flags; + } + + GrGpuResource* resource = this->findAndRefCachedResource(*key); + if (resource) { + SkASSERT(static_cast<GrSurface*>(resource)->asTexture()); + return static_cast<GrSurface*>(resource)->asTexture(); + } + return NULL; +} + +bool GrContext::isTextureInCache(const GrSurfaceDesc& desc, + const GrContentKey& origKey, + const GrTextureParams* params) const { + uint32_t flags = get_texture_flags(fGpu, params, desc); + SkTCopyOnFirstWrite<GrContentKey> key(origKey); + if (flags) { + GrContentKey::Builder builder(key.writable(), origKey, ResizeDomain(), 1); + builder[0] = flags; + } + + return fResourceCache2->hasContentKey(*key); } GrTexture* GrContext::refScratchTexture(const GrSurfaceDesc& inDesc, ScratchTexMatch match, @@ -316,6 +526,19 @@ GrTexture* GrContext::createUncachedTexture(const GrSurfaceDesc& desc, return fGpu->createTexture(desc, false, srcData, rowBytes); } +void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes) const { + if (maxTextures) { + *maxTextures = fResourceCache2->getMaxResourceCount(); + } + if (maxTextureBytes) { + *maxTextureBytes = fResourceCache2->getMaxResourceBytes(); + } +} + +void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) { + fResourceCache2->setLimits(maxTextures, maxTextureBytes); +} + int GrContext::getMaxTextureSize() const { return SkTMin(fGpu->caps()->maxTextureSize(), fMaxTextureSizeOverride); } @@ -340,9 +563,22 @@ GrRenderTarget* GrContext::wrapBackendRenderTarget(const GrBackendRenderTargetDe /////////////////////////////////////////////////////////////////////////////// -bool GrContext::supportsIndex8PixelConfig() const { +bool GrContext::supportsIndex8PixelConfig(const GrTextureParams* params, + int width, int height) const { const GrDrawTargetCaps* caps = fGpu->caps(); - return caps->isConfigTexturable(kIndex_8_GrPixelConfig); + if (!caps->isConfigTexturable(kIndex_8_GrPixelConfig)) { + return false; + } + + bool isPow2 = SkIsPow2(width) && SkIsPow2(height); + + if (!isPow2) { + bool tiled = params && params->isTiled(); + if (tiled && !caps->npotTextureTileSupport()) { + return false; + } + } + return true; } @@ -1531,39 +1767,14 @@ const GrFragmentProcessor* GrContext::createUPMToPMEffect(GrTexture* texture, } } -////////////////////////////////////////////////////////////////////////////// - -void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes) const { - if (maxTextures) { - *maxTextures = fResourceCache2->getMaxResourceCount(); - } - if (maxTextureBytes) { - *maxTextureBytes = fResourceCache2->getMaxResourceBytes(); - } -} - -void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) { - fResourceCache2->setLimits(maxTextures, maxTextureBytes); -} - -bool GrContext::addResourceToCache(const GrContentKey& key, GrGpuResource* resource) { - ASSERT_OWNED_RESOURCE(resource); - if (!resource || resource->wasDestroyed()) { - return false; - } - return resource->cacheAccess().setContentKey(key); -} - -bool GrContext::isResourceInCache(const GrContentKey& key) const { - return fResourceCache2->hasContentKey(key); +void GrContext::addResourceToCache(const GrContentKey& key, GrGpuResource* resource) { + resource->cacheAccess().setContentKey(key); } GrGpuResource* GrContext::findAndRefCachedResource(const GrContentKey& key) { return fResourceCache2->findAndRefContentResource(key); } -////////////////////////////////////////////////////////////////////////////// - void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) { fGpu->addGpuTraceMarker(marker); if (fDrawBuffer) { |