Exemple #1
0
void LayerTextureUpdaterSkPicture::updateTextureRect(LayerTexture* texture, const IntRect& sourceRect, const IntRect& destRect)
{
    if (m_createFrameBuffer) {
        deleteFrameBuffer();
        createFrameBuffer();
        m_createFrameBuffer = false;
    }
    if (!m_fbo)
        return;

    // Bind texture.
    context()->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
    texture->framebufferTexture2D();
    ASSERT(context()->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) == GraphicsContext3D::FRAMEBUFFER_COMPLETE);

    // Notify SKIA to sync its internal GL state.
    m_skiaContext->resetContext();
    m_canvas->save();
    m_canvas->clipRect(SkRect(destRect));
    // Translate the origin of contentRect to that of destRect.
    // Note that destRect is defined relative to sourceRect.
    m_canvas->translate(contentRect().x() - sourceRect.x() + destRect.x(),
                        contentRect().y() - sourceRect.y() + destRect.y());
    m_canvas->drawPicture(m_picture);
    m_canvas->restore();
    // Flush SKIA context so that all the rendered stuff appears on the texture.
    m_skiaContext->flush(GrContext::kForceCurrentRenderTarget_FlushBit);

    // Unbind texture.
    context()->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, 0, 0);
    context()->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0);
}
void FrameBufferSkPictureCanvasLayerTextureUpdater::updateTextureRect(CCGraphicsContext* context, TextureAllocator* allocator, ManagedTexture* texture, const IntRect& sourceRect, const IntRect& destRect)
{
    GraphicsContext3D* context3d = context->context3D();
    if (!context3d) {
        // FIXME: Implement this path for software compositing.
        return;
    }

    // Make sure ganesh uses the correct GL context.
    context3d->makeContextCurrent();
    // Notify ganesh to sync its internal GL state.
    context3d->grContext()->resetContext();

    // Create an accelerated canvas to draw on.
    OwnPtr<SkCanvas> canvas = createAcceleratedCanvas(context3d, allocator, texture);

    // The compositor expects the textures to be upside-down so it can flip
    // the final composited image. Ganesh renders the image upright so we
    // need to do a y-flip.
    canvas->translate(0.0, texture->size().height());
    canvas->scale(1.0, -1.0);
    // Only the region corresponding to destRect on the texture must be updated.
    canvas->clipRect(SkRect(destRect));
    // Translate the origin of contentRect to that of destRect.
    // Note that destRect is defined relative to sourceRect.
    canvas->translate(contentRect().x() - sourceRect.x() + destRect.x(),
                      contentRect().y() - sourceRect.y() + destRect.y());
    drawPicture(canvas.get());

    // Flush ganesh context so that all the rendered stuff appears on the texture.
    context3d->grContext()->flush();
}
SkImageFilter::SkImageFilter(SkImageFilter* input, const CropRect* cropRect)
  : fInputCount(1),
    fInputs(new SkImageFilter*[1]),
    fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)) {
    fInputs[0] = input;
    SkSafeRef(fInputs[0]);
}
SkImageFilter::SkImageFilter(SkImageFilter* input1, SkImageFilter* input2, const CropRect* cropRect)
  : fInputCount(2), fInputs(new SkImageFilter*[2]),
    fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)) {
    fInputs[0] = input1;
    fInputs[1] = input2;
    SkSafeRef(fInputs[0]);
    SkSafeRef(fInputs[1]);
}
Exemple #5
0
SkImageFilter::SkImageFilter(int inputCount, SkReadBuffer& buffer)
    : fUsesSrcInput(false)
    , fCropRect(SkRect(), 0x0)
    , fUniqueID(next_image_filter_unique_id()) {
    Common common;
    if (common.unflatten(buffer, inputCount)) {
        this->init(common.inputs(), common.inputCount(), &common.cropRect());
    }
}
SkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect)
  : fInputCount(inputCount),
    fInputs(new SkImageFilter*[inputCount]),
    fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)) {
    for (int i = 0; i < inputCount; ++i) {
        fInputs[i] = inputs[i];
        SkSafeRef(fInputs[i]);
    }
}
Exemple #7
0
SkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect)
  : fInputCount(inputCount),
    fInputs(new SkImageFilter*[inputCount]),
    fUsesSrcInput(false),
    fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)),
    fUniqueID(next_image_filter_unique_id()) {
    for (int i = 0; i < inputCount; ++i) {
        if (NULL == inputs[i] || inputs[i]->usesSrcInput()) {
            fUsesSrcInput = true;
        }
        fInputs[i] = inputs[i];
        SkSafeRef(fInputs[i]);
    }
}
Exemple #8
0
void SkImageFilter::init(sk_sp<SkImageFilter>* inputs,
                         int inputCount,
                         const CropRect* cropRect) {
    fCropRect = cropRect ? *cropRect : CropRect(SkRect(), 0x0);

    fInputs.reset(inputCount);

    for (int i = 0; i < inputCount; ++i) {
        if (!inputs[i] || inputs[i]->usesSrcInput()) {
            fUsesSrcInput = true;
        }
        fInputs[i] = inputs[i];
    }
}
GLuint VideoLayerAndroid::createTextureFromImage(int buttonType)
{
    SkRect rect = SkRect(buttonRect);
    SkBitmap bitmap;
    bitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height());
    bitmap.allocPixels();
    bitmap.eraseColor(0);

    SkCanvas canvas(bitmap);
    canvas.drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode);
    RenderSkinMediaButton::Draw(&canvas, buttonRect, buttonType, true);

    GLuint texture;
    glGenTextures(1, &texture);

    GLUtils::createTextureWithBitmap(texture, bitmap);
    bitmap.reset();
    return texture;
}
Exemple #10
0
void LayerTextureUpdaterSkPicture::updateTextureRect(GraphicsContext3D* context, TextureAllocator* allocator, ManagedTexture* texture, const IntRect& sourceRect, const IntRect& destRect)
{
    // Make sure SKIA uses the correct GL context.
    context->makeContextCurrent();
    // Notify SKIA to sync its internal GL state.
    context->grContext()->resetContext();

    // Create an accelerated canvas to draw on.
    FrameBuffer buffer;
    SkCanvas* canvas = buffer.initialize(context, allocator, texture);

    canvas->clipRect(SkRect(destRect));
    // Translate the origin of contentRect to that of destRect.
    // Note that destRect is defined relative to sourceRect.
    canvas->translate(contentRect().x() - sourceRect.x() + destRect.x(),
                      contentRect().y() - sourceRect.y() + destRect.y());
    canvas->drawPicture(m_picture);

    // Flush SKIA context so that all the rendered stuff appears on the texture.
    context->grContext()->flush();
}
void LayerTextureUpdaterSkPicture::updateTextureRect(GraphicsContext3D* compositorContext, TextureAllocator* allocator, ManagedTexture* texture, const IntRect& sourceRect, const IntRect& destRect)
{
    ASSERT(!m_context || m_context == compositorContext);
    m_context = compositorContext;

    if (m_createFrameBuffer) {
        deleteFrameBuffer();
        createFrameBuffer();
        m_createFrameBuffer = false;
    }
    if (!m_fbo)
        return;

    // Bind texture.
    context()->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
    texture->framebufferTexture2D(context(), allocator);
    ASSERT(context()->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) == GraphicsContext3D::FRAMEBUFFER_COMPLETE);

    // Make sure SKIA uses the correct GL context.
    context()->makeContextCurrent();

    GrContext* skiaContext = m_context->grContext();
    // Notify SKIA to sync its internal GL state.
    skiaContext->resetContext();
    m_canvas->save();
    m_canvas->clipRect(SkRect(destRect));
    // Translate the origin of contentRect to that of destRect.
    // Note that destRect is defined relative to sourceRect.
    m_canvas->translate(contentRect().x() - sourceRect.x() + destRect.x(),
                        contentRect().y() - sourceRect.y() + destRect.y());
    m_canvas->drawPicture(m_picture);
    m_canvas->restore();
    // Flush SKIA context so that all the rendered stuff appears on the texture.
    skiaContext->flush();

    // Unbind texture.
    context()->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, 0, 0);
    context()->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0);
}
Exemple #12
0
void LayerAndroid::dumpLayer(FILE* file, int indentLevel) const
{
    writeHexVal(file, indentLevel + 1, "layer", (int)this);
    writeIntVal(file, indentLevel + 1, "layerId", m_uniqueId);
    writeIntVal(file, indentLevel + 1, "haveClip", m_haveClip);
    writeIntVal(file, indentLevel + 1, "isFixed", isPositionFixed());

    writeFloatVal(file, indentLevel + 1, "opacity", getOpacity());
    writeSize(file, indentLevel + 1, "size", getSize());
    writePoint(file, indentLevel + 1, "position", getPosition());
    writePoint(file, indentLevel + 1, "anchor", getAnchorPoint());

    writeMatrix(file, indentLevel + 1, "drawMatrix", m_drawTransform);
    writeMatrix(file, indentLevel + 1, "transformMatrix", m_transform);
    writeRect(file, indentLevel + 1, "clippingRect", SkRect(m_clippingRect));

    if (m_content) {
        writeIntVal(file, indentLevel + 1, "m_content.width", m_content->width());
        writeIntVal(file, indentLevel + 1, "m_content.height", m_content->height());
    }

    if (m_fixedPosition)
        return m_fixedPosition->dumpLayer(file, indentLevel);
}
Exemple #13
0
static void test_drawPathEmpty(skiatest::Reporter*, SkCanvas* canvas) {
    // Filling an empty path should not crash.
    SkPaint paint;
    canvas->drawRect(SkRect(), paint);
    canvas->drawPath(SkPath(), paint);
    canvas->drawOval(SkRect(), paint);
    canvas->drawRect(SkRect(), paint);
    canvas->drawRRect(SkRRect(), paint);

    // Stroking an empty path should not crash.
    paint.setAntiAlias(true);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setColor(SK_ColorGRAY);
    paint.setStrokeWidth(SkIntToScalar(20));
    paint.setStrokeJoin(SkPaint::kRound_Join);
    canvas->drawRect(SkRect(), paint);
    canvas->drawPath(SkPath(), paint);
    canvas->drawOval(SkRect(), paint);
    canvas->drawRect(SkRect(), paint);
    canvas->drawRRect(SkRRect(), paint);
}
bool VideoLayerAndroid::drawGL()
{
    // Lazily allocated the textures.
    if (!m_createdTexture) {
        m_backgroundTextureId = createBackgroundTexture();
        m_spinnerOuterTextureId = createSpinnerOuterTexture();
        m_spinnerInnerTextureId = createSpinnerInnerTexture();
        m_posterTextureId = createPosterTexture();
        m_createdTexture = true;
    }

    SkRect rect = SkRect::MakeSize(getSize());
    GLfloat surfaceMatrix[16];

    SkRect innerRect = SkRect(buttonRect);
    if (innerRect.contains(rect))
        innerRect = rect;

    innerRect.offset((rect.width() - IMAGESIZE) / 2 , (rect.height() - IMAGESIZE) / 2);

    // Draw the poster image, the progressing image or the Video depending
    // on the player's state.
    if (m_playerState == PREPARING) {
        // Show the progressing animation, with two rotating circles
		// SSG
		if (m_surfaceTexture.get() && (m_surfaceTexture->getTimestamp() > 0)) {
			m_surfaceTexture->getTransformMatrix(surfaceMatrix);
			GLuint textureId =
				TilesManager::instance()->videoLayerManager()->getTextureId(uniqueId());
			TilesManager::instance()->shader()->drawVideoLayerQuad(m_drawTransform,
					surfaceMatrix,
					rect, textureId);
			TilesManager::instance()->videoLayerManager()->updateMatrix(uniqueId(),
					surfaceMatrix);
		} else {
			TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, rect,
					m_backgroundTextureId,
					1, true);
		}

        TransformationMatrix addReverseRotation;
        TransformationMatrix addRotation = m_drawTransform;
        addRotation.translate(innerRect.fLeft, innerRect.fTop);
        addRotation.translate(IMAGESIZE / 2, IMAGESIZE / 2);
        addReverseRotation = addRotation;
        addRotation.rotate(m_rotateDegree);
        addRotation.translate(-IMAGESIZE / 2, -IMAGESIZE / 2);

        SkRect size = SkRect::MakeWH(innerRect.width(), innerRect.height());
        TilesManager::instance()->shader()->drawLayerQuad(addRotation, size,
                                                          m_spinnerOuterTextureId,
                                                          1, true);

        addReverseRotation.rotate(-m_rotateDegree);
        addReverseRotation.translate(-IMAGESIZE / 2, -IMAGESIZE / 2);

        TilesManager::instance()->shader()->drawLayerQuad(addReverseRotation, size,
                                                          m_spinnerInnerTextureId,
                                                          1, true);

        m_rotateDegree += ROTATESTEP;

    } else if (m_playerState == PLAYING && m_surfaceTexture.get()) {
        // Show the real video.
        m_surfaceTexture->updateTexImage();
        m_surfaceTexture->getTransformMatrix(surfaceMatrix);
        GLuint textureId =
            TilesManager::instance()->videoLayerManager()->getTextureId(uniqueId());
        TilesManager::instance()->shader()->drawVideoLayerQuad(m_drawTransform,
                                                               surfaceMatrix,
                                                               rect, textureId);
        TilesManager::instance()->videoLayerManager()->updateMatrix(uniqueId(),
                                                                    surfaceMatrix);
    } else {
        GLuint textureId =
            TilesManager::instance()->videoLayerManager()->getTextureId(uniqueId());
        GLfloat* matrix =
            TilesManager::instance()->videoLayerManager()->getMatrix(uniqueId());
        if (textureId && matrix) {
            // Show the screen shot for each video.
            TilesManager::instance()->shader()->drawVideoLayerQuad(m_drawTransform,
                                                               matrix,
                                                               rect, textureId);
        } else {
            // Show the static poster b/c there is no screen shot available.
            TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, rect,
                                                              m_backgroundTextureId,
                                                              1, true);
            TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, innerRect,
                                                              m_posterTextureId,
                                                              1, true);
        }
    }

    return drawChildrenGL();
}
void Font::drawGlyphs(GraphicsContext* graphicsContext,
                      const SimpleFontData* font,
                      const GlyphBuffer& glyphBuffer,
                      int from,
                      int numGlyphs,
                      const FloatPoint& point,
                      const FloatRect& textRect) const
{
    SkColor color = graphicsContext->effectiveFillColor();
    unsigned char alpha = SkColorGetA(color);
    // Skip 100% transparent text; no need to draw anything.
    if (!alpha && graphicsContext->strokeStyle() == NoStroke && !graphicsContext->hasShadow())
        return;

    // We draw the glyphs in chunks to avoid having to do a heap allocation for
    // the arrays of characters and advances.
    const int kMaxBufferLength = 256;
    Vector<int, kMaxBufferLength> advances;
    int glyphIndex = 0;  // The starting glyph of the current chunk.

    float horizontalOffset = point.x(); // The floating point offset of the left side of the current glyph.

#if ENABLE(OPENTYPE_VERTICAL)
    const OpenTypeVerticalData* verticalData = font->verticalData();
    if (verticalData) {
        Vector<FloatPoint, kMaxBufferLength> translations;
        Vector<GOFFSET, kMaxBufferLength> offsets;

        // Skia doesn't have matrix for glyph coordinate space, so we rotate back the CTM.
        AffineTransform savedMatrix = graphicsContext->getCTM();
        graphicsContext->concatCTM(AffineTransform(0, -1, 1, 0, point.x(), point.y()));
        graphicsContext->concatCTM(AffineTransform(1, 0, 0, 1, -point.x(), -point.y()));

        const FontMetrics& metrics = font->fontMetrics();
        SkScalar verticalOriginX = SkFloatToScalar(point.x() + metrics.floatAscent() - metrics.floatAscent(IdeographicBaseline));
        while (glyphIndex < numGlyphs) {
            // How many chars will be in this chunk?
            int curLen = std::min(kMaxBufferLength, numGlyphs - glyphIndex);

            const Glyph* glyphs = glyphBuffer.glyphs(from + glyphIndex);
            translations.resize(curLen);
            verticalData->getVerticalTranslationsForGlyphs(font, &glyphs[0], curLen, reinterpret_cast<float*>(&translations[0]));
            // To position glyphs vertically, we use offsets instead of advances.
            advances.resize(curLen);
            advances.fill(0);
            offsets.resize(curLen);
            float currentWidth = 0;
            for (int i = 0; i < curLen; ++i, ++glyphIndex) {
                offsets[i].du = lroundf(translations[i].x());
                offsets[i].dv = -lroundf(currentWidth - translations[i].y());
                currentWidth += glyphBuffer.advanceAt(from + glyphIndex);
            }
            SkPoint origin;
            origin.set(verticalOriginX, SkFloatToScalar(point.y() + horizontalOffset - point.x()));
            horizontalOffset += currentWidth;
            paintSkiaText(graphicsContext, font->platformData(), curLen, &glyphs[0], &advances[0], &offsets[0], origin, SkRect(textRect));
        }

        graphicsContext->setCTM(savedMatrix);
        return;
    }
#endif

    // In order to round all offsets to the correct pixel boundary, this code keeps track of the absolute position
    // of each glyph in floating point units and rounds to integer advances at the last possible moment.

    int lastHorizontalOffsetRounded = lroundf(horizontalOffset); // The rounded offset of the left side of the last glyph rendered.
    Vector<WORD, kMaxBufferLength> glyphs;
    while (glyphIndex < numGlyphs) {
        // How many chars will be in this chunk?
        int curLen = std::min(kMaxBufferLength, numGlyphs - glyphIndex);
        glyphs.resize(curLen);
        advances.resize(curLen);

        float currentWidth = 0;
        for (int i = 0; i < curLen; ++i, ++glyphIndex) {
            glyphs[i] = glyphBuffer.glyphAt(from + glyphIndex);
            horizontalOffset += glyphBuffer.advanceAt(from + glyphIndex);
            advances[i] = lroundf(horizontalOffset) - lastHorizontalOffsetRounded;
            lastHorizontalOffsetRounded += advances[i];
            currentWidth += glyphBuffer.advanceAt(from + glyphIndex);

            // Bug 26088 - very large positive or negative runs can fail to
            // render so we clamp the size here. In the specs, negative
            // letter-spacing is implementation-defined, so this should be
            // fine, and it matches Safari's implementation. The call actually
            // seems to crash if kMaxNegativeRun is set to somewhere around
            // -32830, so we give ourselves a little breathing room.
            const int maxNegativeRun = -32768;
            const int maxPositiveRun =  32768;
            if ((currentWidth + advances[i] < maxNegativeRun) || (currentWidth + advances[i] > maxPositiveRun))
                advances[i] = 0;
        }

        SkPoint origin = point;
        origin.fX += SkFloatToScalar(horizontalOffset - point.x() - currentWidth);
        paintSkiaText(graphicsContext, font->platformData(), curLen, &glyphs[0], &advances[0], 0, origin, SkRect(textRect));
    }
}