예제 #1
0
void TextureCache::uploadToTexture(GLint id, bool resize, GLenum format, GLsizei stride, GLsizei bpp,
        GLsizei width, GLsizei height, GLenum type, const GLvoid * data) {
    const bool useStride = stride != width && Extensions::getInstance().hasUnpackRowLength();
    if ((stride == width) || useStride) {
        if (useStride) {
            glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
        }

        if (resize) {
            glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, data);
            TT_ADD(id, width, height, format, type, String8("texture"), "[TextureCache.cpp] uploadToTexture +");
        } else {
            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, data);
        }

        if (useStride) {
            glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
        }
    } else {
        //  With OpenGL ES 2.0 we need to copy the bitmap in a temporary buffer
        //  if the stride doesn't match the width

        GLvoid * temp = (GLvoid *) malloc(width * height * bpp);
        if (!temp) return;

        uint8_t * pDst = (uint8_t *)temp;
        uint8_t * pSrc = (uint8_t *)data;
        for (GLsizei i = 0; i < height; i++) {
            memcpy(pDst, pSrc, width * bpp);
            pDst += width * bpp;
            pSrc += stride * bpp;
        }

        if (resize) {
            glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, temp);
            TT_ADD(id, width, height, format, type, String8("texture"), "[TextureCache.cpp] uploadToTexture +");
        } else {
            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, temp);
        }

        free(temp);
    }
}
예제 #2
0
Layer* LayerRenderer::createRenderLayer(RenderState& renderState, uint32_t width, uint32_t height) {
    ATRACE_CALL();
    LAYER_RENDERER_LOGD("Requesting new render layer %dx%d", width, height);

    Caches& caches = Caches::getInstance();
    GLuint fbo = caches.fboCache.get();
    if (!fbo) {
        ALOGW("Could not obtain an FBO");
        return NULL;
    }

    caches.activeTexture(0);
    Layer* layer = caches.layerCache.get(renderState, width, height);
    if (!layer) {
        ALOGW("Could not obtain a layer");
        return NULL;
    }

    // We first obtain a layer before comparing against the max texture size
    // because layers are not allocated at the exact desired size. They are
    // always created slighly larger to improve recycling
    const uint32_t maxTextureSize = caches.maxTextureSize;
    if (layer->getWidth() > maxTextureSize || layer->getHeight() > maxTextureSize) {
        ALOGW("Layer exceeds max. dimensions supported by the GPU (%dx%d, max=%dx%d)",
                width, height, maxTextureSize, maxTextureSize);

        // Creating a new layer always increment its refcount by 1, this allows
        // us to destroy the layer object if one was created for us
        ResourceCache::getInstance().decrementRefcount(layer);

        return NULL;
    }

    layer->setFbo(fbo);
    layer->layer.set(0.0f, 0.0f, width, height);
    layer->texCoords.set(0.0f, height / float(layer->getHeight()),
            width / float(layer->getWidth()), 0.0f);
    layer->setAlpha(255, SkXfermode::kSrcOver_Mode);
    layer->setColorFilter(NULL);
    layer->setDirty(true);
    layer->region.clear();

    GLuint previousFbo = renderState.getFramebuffer();

    renderState.bindFramebuffer(layer->getFbo());
    layer->bindTexture();

    // Initialize the texture if needed
    if (layer->isEmpty()) {
        layer->setEmpty(false);
        layer->allocateTexture();
        TT_ADD(String8("Layer"), layer->getTexture(), layer->getWidth(), layer->getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, String8("layer"), "[LayerRenderer.cpp] allocateTexture +");

        // This should only happen if we run out of memory
        if (glGetError() != GL_NO_ERROR) {
            ALOGE("Could not allocate texture for layer (fbo=%d %dx%d)", fbo, width, height);
            renderState.bindFramebuffer(previousFbo);
            ResourceCache::getInstance().decrementRefcount(layer);
            return NULL;
        }
    }

    LAYER_RENDERER_LOGD("createRenderLayer %p, %dx%d, fbo %d, texture %d, alpha %d",
            layer, layer->getWidth(), layer->getHeight(), layer->getFbo(), layer->getTexture(), layer->getAlpha());

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
            layer->getTexture(), 0);

    LAYER_RENDERER_LOGD("Layer %p finished uploading texture %d to fbo %d", layer, layer->getTexture(), layer->getFbo());

    renderState.bindFramebuffer(previousFbo);

    return layer;
}
예제 #3
0
ShadowTexture* TextDropShadowCache::get(const SkPaint* paint, const char* text, uint32_t len,
        int numGlyphs, float radius, const float* positions) {
    ShadowText entry(paint, radius, len, text, positions);
    ShadowTexture* texture = mCache.get(entry);

    if (!texture) {
        SkPaint paintCopy(*paint);
        paintCopy.setTextAlign(SkPaint::kLeft_Align);
        FontRenderer::DropShadow shadow = mRenderer->renderDropShadow(&paintCopy, text, 0,
                len, numGlyphs, radius, positions);

        if (!shadow.image) {
            return NULL;
        }

        Caches& caches = Caches::getInstance();

        texture = new ShadowTexture(caches);
        texture->left = shadow.penX;
        texture->top = shadow.penY;
        texture->width = shadow.width;
        texture->height = shadow.height;
        texture->generation = 0;
        texture->blend = true;

        const uint32_t size = shadow.width * shadow.height;
        texture->bitmapSize = size;

        // Don't even try to cache a bitmap that's bigger than the cache
        if (size < mMaxSize) {
            while (mSize + size > mMaxSize) {
                mCache.removeOldest();
            }
        }

        glGenTextures(1, &texture->id);

        caches.bindTexture(texture->id);
        // Textures are Alpha8
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

        glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texture->width, texture->height, 0,
                GL_ALPHA, GL_UNSIGNED_BYTE, shadow.image);

        TT_ADD(texture->id, texture->width, texture->height, GL_ALPHA, GL_UNSIGNED_BYTE, String8("textShadow"), "[TextDropShadowCache.cpp] get +");
        DUMP_ALPHA_TEXTURE(texture->width, texture->height, shadow.image, "ShadowTexture", SkBitmap::kA8_Config);

        texture->setFilter(GL_LINEAR);
        texture->setWrap(GL_CLAMP_TO_EDGE);

        if (size < mMaxSize) {
            if (mDebugEnabled) {
                ALOGD("Shadow texture created, size = %d", texture->bitmapSize);
            }

            entry.copyTextLocally();

            mSize += size;
            mCache.put(entry, texture);
        } else {
            texture->cleanup = true;
        }

        // Cleanup shadow
        free(shadow.image);
    }

    return texture;
}