bool GrGpu::attachStencilBufferToRenderTarget(GrRenderTarget* rt) { SkASSERT(NULL == rt->renderTargetPriv().getStencilBuffer()); GrUniqueKey sbKey; int width = rt->width(); int height = rt->height(); if (this->caps()->oversizedStencilSupport()) { width = SkNextPow2(width); height = SkNextPow2(height); } GrStencilBuffer::ComputeSharedStencilBufferKey(width, height, rt->numSamples(), &sbKey); SkAutoTUnref<GrStencilBuffer> sb(static_cast<GrStencilBuffer*>( this->getContext()->getResourceCache()->findAndRefUniqueResource(sbKey))); if (sb) { if (this->attachStencilBufferToRenderTarget(sb, rt)) { rt->renderTargetPriv().didAttachStencilBuffer(sb); return true; } return false; } if (this->createStencilBufferForRenderTarget(rt, width, height)) { GrStencilBuffer* sb = rt->renderTargetPriv().getStencilBuffer(); sb->resourcePriv().setUniqueKey(sbKey); return true; } else { return false; } }
SkGLDevice_FBO::SkGLDevice_FBO(const SkBitmap& bitmap, bool offscreen) : SkGLDevice(bitmap, offscreen) { fFBO = 0; fTextureID = 0; if (offscreen) { int nw = SkNextPow2(bitmap.rowBytesAsPixels()); int nh = SkNextPow2(bitmap.height()); glGenFramebuffersEXT(1, &fFBO); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fFBO); glGenTextures(1, &fTextureID); glBindTexture(GL_TEXTURE_2D, fTextureID); SkGL::SetTexParamsClamp(false); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, nw, nh, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fTextureID, 0); GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { SkDebugf("-- glCheckFramebufferStatusEXT %x\n", status); } // now reset back to "normal" drawing target glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } }
SkGLTextCache::Strike::Strike(Strike* next, int width, int height) { fStrikeWidth = SkNextPow2(SkMax32(kMinStrikeWidth, width)); fStrikeHeight = SkNextPow2(height); fGlyphCount = 0; fNextFreeOffsetX = 0; fNext = next; fStrikeWidthShift = SkNextLog2(fStrikeWidth); fStrikeHeightShift = SkNextLog2(fStrikeHeight); if (next) { SkASSERT(next->fStrikeHeight == fStrikeHeight); } // create an empty texture to receive glyphs fTexName = 0; glGenTextures(1, &fTexName); glBindTexture(GL_TEXTURE_2D, fTexName); glTexImage2D(GL_TEXTURE_2D, 0, gTextTextureFormat, fStrikeWidth, fStrikeHeight, 0, gTextTextureFormat, gTextTextureType, NULL); SK_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); SK_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); SK_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); SK_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); }
void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, U16CPU width, U16CPU height, SkIPoint origin, const GrCaps& caps, SkImageUsageType usage) { const Stretch::Type stretches[] = { Stretch::kNone_Type, // kUntiled_SkImageUsageType Stretch::kNearest_Type, // kTiled_Unfiltered_SkImageUsageType Stretch::kBilerp_Type, // kTiled_Filtered_SkImageUsageType }; const bool isPow2 = SkIsPow2(width) && SkIsPow2(height); const bool needToStretch = !isPow2 && usage != kUntiled_SkImageUsageType && !caps.npotTextureTileSupport(); if (needToStretch) { GrUniqueKey tmpKey; make_unstretched_key(&tmpKey, imageID, width, height, origin); Stretch stretch; stretch.fType = stretches[usage]; stretch.fWidth = SkNextPow2(width); stretch.fHeight = SkNextPow2(height); if (!make_stretched_key(tmpKey, stretch, key)) { goto UNSTRETCHED; } } else { UNSTRETCHED: make_unstretched_key(key, imageID, width, height, origin); } }
/* Return true if the bitmap cannot be supported in its current config as a texture, and it needs to be promoted to ARGB32. */ static bool needToPromoteTo32bit(const SkBitmap& bitmap) { if (bitmap.config() == SkBitmap::kIndex8_Config) { #ifdef SK_GL_SUPPORT_COMPRESSEDTEXIMAGE2D const int w = bitmap.width(); const int h = bitmap.height(); if (SkNextPow2(w) == w && SkNextPow2(h) == h) { // we can handle Indx8 if we're a POW2 return false; } #endif return true; // must promote to ARGB32 } return false; }
GrStencilAttachment* GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt) { SkASSERT(rt); if (rt->renderTargetPriv().getStencilAttachment()) { return rt->renderTargetPriv().getStencilAttachment(); } if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment()) { GrUniqueKey sbKey; int width = rt->width(); int height = rt->height(); #if 0 if (this->caps()->oversizedStencilSupport()) { width = SkNextPow2(width); height = SkNextPow2(height); } #endif bool newStencil = false; GrStencilAttachment::ComputeSharedStencilAttachmentKey(width, height, rt->numStencilSamples(), &sbKey); GrStencilAttachment* stencil = static_cast<GrStencilAttachment*>( this->findAndRefResourceByUniqueKey(sbKey)); if (!stencil) { // Need to try and create a new stencil stencil = this->gpu()->createStencilAttachmentForRenderTarget(rt, width, height); if (stencil) { stencil->resourcePriv().setUniqueKey(sbKey); newStencil = true; } } if (rt->renderTargetPriv().attachStencilAttachment(stencil)) { if (newStencil) { // Right now we're clearing the stencil attachment here after it is // attached to a RT for the first time. When we start matching // stencil buffers with smaller color targets this will no longer // be correct because it won't be guaranteed to clear the entire // sb. // We used to clear down in the GL subclass using a special purpose // FBO. But iOS doesn't allow a stencil-only FBO. It reports unsupported // FBO status. this->gpu()->clearStencil(rt); } } } return rt->renderTargetPriv().getStencilAttachment(); }
bool GrGpu::attachStencilAttachmentToRenderTarget(GrRenderTarget* rt) { SkASSERT(NULL == rt->renderTargetPriv().getStencilAttachment()); GrUniqueKey sbKey; int width = rt->width(); int height = rt->height(); #if 0 if (this->caps()->oversizedStencilSupport()) { width = SkNextPow2(width); height = SkNextPow2(height); } #endif GrStencilAttachment::ComputeSharedStencilAttachmentKey(width, height, rt->numStencilSamples(), &sbKey); SkAutoTUnref<GrStencilAttachment> sb(static_cast<GrStencilAttachment*>( this->getContext()->getResourceCache()->findAndRefUniqueResource(sbKey))); if (sb) { if (this->attachStencilAttachmentToRenderTarget(sb, rt)) { rt->renderTargetPriv().didAttachStencilAttachment(sb); return true; } return false; } if (this->createStencilAttachmentForRenderTarget(rt, width, height)) { // Right now we're clearing the stencil buffer here after it is // attached to an RT for the first time. When we start matching // stencil buffers with smaller color targets this will no longer // be correct because it won't be guaranteed to clear the entire // sb. // We used to clear down in the GL subclass using a special purpose // FBO. But iOS doesn't allow a stencil-only FBO. It reports unsupported // FBO status. this->clearStencil(rt); GrStencilAttachment* sb = rt->renderTargetPriv().getStencilAttachment(); sb->resourcePriv().setUniqueKey(sbKey); return true; } else { return false; } }
void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& subset, const GrCaps& caps, SkImageUsageType usage) { const SkGrStretch::Type stretches[] = { SkGrStretch::kNone_Type, // kUntiled_SkImageUsageType SkGrStretch::kNearest_Type, // kTiled_Unfiltered_SkImageUsageType SkGrStretch::kBilerp_Type, // kTiled_Filtered_SkImageUsageType }; if (!GrTextureUsageSupported(caps, subset.width(), subset.height(), usage)) { GrUniqueKey tmpKey; make_unstretched_key(&tmpKey, imageID, subset); SkGrStretch stretch; stretch.fType = stretches[usage]; stretch.fWidth = SkNextPow2(subset.width()); stretch.fHeight = SkNextPow2(subset.height()); if (!GrMakeStretchedKey(tmpKey, stretch, key)) { goto UNSTRETCHED; } } else { UNSTRETCHED: make_unstretched_key(key, imageID, subset); } }
GLuint SkGL::BindNewTexture(const SkBitmap& origBitmap, SkPoint* max) { SkBitmap tmpBitmap; const SkBitmap* bitmap = &origBitmap; if (needToPromoteTo32bit(origBitmap)) { origBitmap.copyTo(&tmpBitmap, SkBitmap::kARGB_8888_Config); // now bitmap points to our temp, which has been promoted to 32bits bitmap = &tmpBitmap; } GLenum format, type; if (!canBeTexture(*bitmap, &format, &type)) { return 0; } SkAutoLockPixels alp(*bitmap); if (!bitmap->readyToDraw()) { return 0; } GLuint textureName; glGenTextures(1, &textureName); glBindTexture(GL_TEXTURE_2D, textureName); // express rowbytes as a number of pixels for ow int ow = bitmap->rowBytesAsPixels(); int oh = bitmap->height(); int nw = SkNextPow2(ow); int nh = SkNextPow2(oh); glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel()); // check if we need to scale to create power-of-2 dimensions #ifdef SK_GL_SUPPORT_COMPRESSEDTEXIMAGE2D if (SkBitmap::kIndex8_Config == bitmap->config()) { size_t imagesize = bitmap->getSize() + SK_GL_SIZE_OF_PALETTE; SkAutoMalloc storage(imagesize); build_compressed_data(storage.get(), *bitmap); // we only support POW2 here (GLES 1.0 restriction) SkASSERT(ow == nw); SkASSERT(oh == nh); glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, ow, oh, 0, imagesize, storage.get()); } else // fall through to non-compressed logic #endif { if (ow != nw || oh != nh) { glTexImage2D(GL_TEXTURE_2D, 0, format, nw, nh, 0, format, type, NULL); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, ow, oh, format, type, bitmap->getPixels()); } else { // easy case, the bitmap is already pow2 glTexImage2D(GL_TEXTURE_2D, 0, format, ow, oh, 0, format, type, bitmap->getPixels()); } } #ifdef TRACE_TEXTURE_CREATION SkDebugf("--- new texture [%d] size=(%d %d) bpp=%d\n", textureName, ow, oh, bitmap->bytesPerPixel()); #endif if (max) { max->fX = SkFixedToScalar(bitmap->width() << (16 - SkNextLog2(nw))); max->fY = SkFixedToScalar(oh << (16 - SkNextLog2(nh))); } return textureName; }
static inline bool check_rounding(int value, int dividend, int divisor) { // returns true if the value is greater than floor(dividend/divisor) // and less than SkNextPow2(ceil(dividend - divisor)) return (((divisor * value) > (dividend - divisor)) && value <= SkNextPow2(((dividend - 1) / divisor) + 1)); }
SkGLTextCache::Strike* SkGLTextCache::Strike::findGlyph(const SkGlyph& glyph, int* offset) { Strike* strike = this; SkDEBUGCODE(const int height = SkNextPow2(glyph.fHeight);) do {