GrContext::TextureCacheEntry sk_gr_create_bitmap_texture(GrContext* ctx, GrContext::TextureKey key, const GrSamplerState& sampler, const SkBitmap& origBitmap) { SkAutoLockPixels alp(origBitmap); GrContext::TextureCacheEntry entry; if (!origBitmap.readyToDraw()) { return entry; } SkBitmap tmpBitmap; const SkBitmap* bitmap = &origBitmap; GrTextureDesc desc = { kNone_GrTextureFlags, kNone_GrAALevel, bitmap->width(), bitmap->height(), SkGr::Bitmap2PixelConfig(*bitmap) }; if (SkBitmap::kIndex8_Config == bitmap->config()) { // build_compressed_data doesn't do npot->pot expansion // and paletted textures can't be sub-updated if (ctx->supportsIndex8PixelConfig(sampler, bitmap->width(), bitmap->height())) { size_t imagesize = bitmap->width() * bitmap->height() + kGrColorTableSize; SkAutoMalloc storage(imagesize); build_compressed_data(storage.get(), origBitmap); // our compressed data will be trimmed, so pass width() for its // "rowBytes", since they are the same now. if (gUNCACHED_KEY != key) { return ctx->createAndLockTexture(key, sampler, desc, storage.get(), bitmap->width()); } else { entry = ctx->lockScratchTexture(desc, GrContext::kExact_ScratchTexMatch); entry.texture()->writePixels(0, 0, bitmap->width(), bitmap->height(), desc.fConfig, storage.get(), 0); return entry; } } else { origBitmap.copyTo(&tmpBitmap, SkBitmap::kARGB_8888_Config); // now bitmap points to our temp, which has been promoted to 32bits bitmap = &tmpBitmap; } } desc.fConfig = SkGr::Bitmap2PixelConfig(*bitmap); if (gUNCACHED_KEY != key) { return ctx->createAndLockTexture(key, sampler, desc, bitmap->getPixels(), bitmap->rowBytes()); } else { entry = ctx->lockScratchTexture(desc, GrContext::kExact_ScratchTexMatch); entry.texture()->writePixels(0, 0, bitmap->width(), bitmap->height(), desc.fConfig, bitmap->getPixels(), bitmap->rowBytes()); return entry; } }
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 GrTexture* sk_gr_create_bitmap_texture(GrContext* ctx, bool cache, const GrTextureParams* params, const SkBitmap& origBitmap) { SkAutoLockPixels alp(origBitmap); if (!origBitmap.readyToDraw()) { return NULL; } SkBitmap tmpBitmap; const SkBitmap* bitmap = &origBitmap; GrTextureDesc desc; generate_bitmap_texture_desc(*bitmap, &desc); if (SkBitmap::kIndex8_Config == bitmap->config()) { // build_compressed_data doesn't do npot->pot expansion // and paletted textures can't be sub-updated if (ctx->supportsIndex8PixelConfig(params, bitmap->width(), bitmap->height())) { size_t imagesize = bitmap->width() * bitmap->height() + kGrColorTableSize; SkAutoMalloc storage(imagesize); build_compressed_data(storage.get(), origBitmap); // our compressed data will be trimmed, so pass width() for its // "rowBytes", since they are the same now. if (cache) { GrCacheID cacheID; generate_bitmap_cache_id(origBitmap, &cacheID); return ctx->createTexture(params, desc, cacheID, storage.get(), bitmap->width()); } else { GrTexture* result = ctx->lockAndRefScratchTexture(desc, GrContext::kExact_ScratchTexMatch); result->writePixels(0, 0, bitmap->width(), bitmap->height(), desc.fConfig, storage.get()); return result; } } else { origBitmap.copyTo(&tmpBitmap, SkBitmap::kARGB_8888_Config); // now bitmap points to our temp, which has been promoted to 32bits bitmap = &tmpBitmap; desc.fConfig = SkBitmapConfig2GrPixelConfig(bitmap->config()); } } if (cache) { // This texture is likely to be used again so leave it in the cache GrCacheID cacheID; generate_bitmap_cache_id(origBitmap, &cacheID); return ctx->createTexture(params, desc, cacheID, bitmap->getPixels(), bitmap->rowBytes()); } else { // This texture is unlikely to be used again (in its present form) so // just use a scratch texture. This will remove the texture from the // cache so no one else can find it. Additionally, once unlocked, the // scratch texture will go to the end of the list for purging so will // likely be available for this volatile bitmap the next time around. GrTexture* result = ctx->lockAndRefScratchTexture(desc, GrContext::kExact_ScratchTexMatch); result->writePixels(0, 0, bitmap->width(), bitmap->height(), desc.fConfig, bitmap->getPixels(), bitmap->rowBytes()); return result; } }