Beispiel #1
0
void FEMorphology::platformApplySoftware()
{
    FilterEffect* in = inputEffect(0);

    Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult();
    if (!dstPixelArray)
        return;

    setIsAlphaImage(in->isAlphaImage());
    if (m_radiusX <= 0 || m_radiusY <= 0) {
        dstPixelArray->zeroFill();
        return;
    }

    Filter& filter = this->filter();
    int radiusX = static_cast<int>(floorf(filter.applyHorizontalScale(m_radiusX)));
    int radiusY = static_cast<int>(floorf(filter.applyVerticalScale(m_radiusY)));

    IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
    RefPtr<Uint8ClampedArray> srcPixelArray = in->asPremultipliedImage(effectDrawingRect);

    PaintingData paintingData;
    paintingData.srcPixelArray = srcPixelArray.get();
    paintingData.dstPixelArray = dstPixelArray;
    paintingData.width = effectDrawingRect.width();
    paintingData.height = effectDrawingRect.height();
    paintingData.radiusX = std::min(effectDrawingRect.width() - 1, radiusX);
    paintingData.radiusY = std::min(effectDrawingRect.height() - 1, radiusY);

    platformApply(&paintingData);
}
Beispiel #2
0
void FEBlend::platformApplySoftware()
{
    FilterEffect* in = inputEffect(0);
    FilterEffect* in2 = inputEffect(1);

    ASSERT(m_mode > FEBLEND_MODE_UNKNOWN);
    ASSERT(m_mode <= FEBLEND_MODE_LIGHTEN);

    Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult();
    if (!dstPixelArray)
        return;

    IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
    RefPtr<Uint8ClampedArray> srcPixelArrayA = in->asPremultipliedImage(effectADrawingRect);

    IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
    RefPtr<Uint8ClampedArray> srcPixelArrayB = in2->asPremultipliedImage(effectBDrawingRect);

    unsigned pixelArrayLength = srcPixelArrayA->length();
    ASSERT(pixelArrayLength == srcPixelArrayB->length());
    for (unsigned pixelOffset = 0; pixelOffset < pixelArrayLength; pixelOffset += 4) {
        unsigned char alphaA = srcPixelArrayA->item(pixelOffset + 3);
        unsigned char alphaB = srcPixelArrayB->item(pixelOffset + 3);
        for (unsigned channel = 0; channel < 3; ++channel) {
            unsigned char colorA = srcPixelArrayA->item(pixelOffset + channel);
            unsigned char colorB = srcPixelArrayB->item(pixelOffset + channel);
            unsigned char result;

            switch (m_mode) {
            case FEBLEND_MODE_NORMAL:
                result = normal(colorA, colorB, alphaA, alphaB);
                break;
            case FEBLEND_MODE_MULTIPLY:
                result = multiply(colorA, colorB, alphaA, alphaB);
                break;
            case FEBLEND_MODE_SCREEN:
                result = screen(colorA, colorB, alphaA, alphaB);
                break;
            case FEBLEND_MODE_DARKEN:
                result = darken(colorA, colorB, alphaA, alphaB);
                break;
            case FEBLEND_MODE_LIGHTEN:
                result = lighten(colorA, colorB, alphaA, alphaB);
                break;
            case FEBLEND_MODE_UNKNOWN:
            default:
                result = 0;
                break;
            }

            dstPixelArray->set(pixelOffset + channel, result);
        }
        unsigned char alphaR = 255 - ((255 - alphaA) * (255 - alphaB)) / 255;
        dstPixelArray->set(pixelOffset + 3, alphaR);
    }
}
Beispiel #3
0
void FETurbulence::applySoftware()
{
    Uint8ClampedArray* pixelArray = createUnmultipliedImageResult();
    if (!pixelArray)
        return;

    if (absolutePaintRect().isEmpty()) {
        pixelArray->zeroFill();
        return;
    }

    PaintingData paintingData(m_seed, roundedIntSize(filterPrimitiveSubregion().size()));
    initPaint(paintingData);

    int optimalThreadNumber = (absolutePaintRect().width() * absolutePaintRect().height()) / s_minimalRectDimension;
    if (optimalThreadNumber > 1) {
        // Initialize parallel jobs
        ParallelJobs<FillRegionParameters> parallelJobs(&WebCore::FETurbulence::fillRegionWorker, optimalThreadNumber);

        // Fill the parameter array
        int i = parallelJobs.numberOfJobs();
        if (i > 1) {
            // Split the job into "stepY"-sized jobs but there a few jobs that need to be slightly larger since
            // stepY * jobs < total size. These extras are handled by the remainder "jobsWithExtra".
            const int stepY = absolutePaintRect().height() / i;
            const int jobsWithExtra = absolutePaintRect().height() % i;

            int startY = 0;
            for (; i > 0; --i) {
                FillRegionParameters& params = parallelJobs.parameter(i-1);
                params.filter = this;
                params.pixelArray = pixelArray;
                params.paintingData = &paintingData;
                params.startY = startY;
                startY += i < jobsWithExtra ? stepY + 1 : stepY;
                params.endY = startY;
                params.baseFrequencyX = m_baseFrequencyX;
                params.baseFrequencyY = m_baseFrequencyY;
            }

            // Execute parallel jobs
            parallelJobs.execute();
            return;
        }
    }

    // Fallback to single threaded mode if there is no room for a new thread or the paint area is too small.
    fillRegion(pixelArray, paintingData, 0, absolutePaintRect().height(), m_baseFrequencyX, m_baseFrequencyY);
}
Beispiel #4
0
void FilterEffect::forceValidPreMultipliedPixels()
{
    // Must operate on pre-multiplied results; other formats cannot have invalid pixels.
    if (!m_premultipliedImageResult)
        return;

    Uint8ClampedArray* imageArray = m_premultipliedImageResult.get();
    unsigned char* pixelData = imageArray->data();
    int pixelArrayLength = imageArray->length();

    // We must have four bytes per pixel, and complete pixels
    ASSERT(!(pixelArrayLength % 4));

#if HAVE(ARM_NEON_INTRINSICS)
    if (pixelArrayLength >= 64) {
        unsigned char* lastPixel = pixelData + (pixelArrayLength & ~0x3f);
        do {
            // Increments pixelData by 64.
            uint8x16x4_t sixteenPixels = vld4q_u8(pixelData);
            sixteenPixels.val[0] = vminq_u8(sixteenPixels.val[0], sixteenPixels.val[3]);
            sixteenPixels.val[1] = vminq_u8(sixteenPixels.val[1], sixteenPixels.val[3]);
            sixteenPixels.val[2] = vminq_u8(sixteenPixels.val[2], sixteenPixels.val[3]);
            vst4q_u8(pixelData, sixteenPixels);
            pixelData += 64;
        } while (pixelData < lastPixel);

        pixelArrayLength &= 0x3f;
        if (!pixelArrayLength)
            return;
    }
#endif

    int numPixels = pixelArrayLength / 4;

    // Iterate over each pixel, checking alpha and adjusting color components if necessary
    while (--numPixels >= 0) {
        // Alpha is the 4th byte in a pixel
        unsigned char a = *(pixelData + 3);
        // Clamp each component to alpha, and increment the pixel location
        for (int i = 0; i < 3; ++i) {
            if (*pixelData > a)
                *pixelData = a;
            ++pixelData;
        }
        // Increment for alpha
        ++pixelData;
    }
}
Beispiel #5
0
bool FECustomFilter::applyShader()
{
    Uint8ClampedArray* dstPixelArray = m_customFilterRenderer->premultipliedAlpha() ? createPremultipliedImageResult() : createUnmultipliedImageResult();
    if (!dstPixelArray)
        return false;

    if (!prepareForDrawing())
        return false;

    FilterEffect* in = inputEffect(0);
    IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
    IntSize newContextSize(effectDrawingRect.size());
    if (!resizeContextIfNeeded(newContextSize))
        return false;

    bool needsInputTexture = m_customFilterRenderer->programNeedsInputTexture();
    if (needsInputTexture) {
        RefPtr<Uint8ClampedArray> srcPixelArray = in->asUnmultipliedImage(effectDrawingRect);
        uploadInputTexture(srcPixelArray.get());
    }
    drawFilterMesh(needsInputTexture ? m_inputTexture : 0);

    ASSERT(static_cast<size_t>(newContextSize.width() * newContextSize.height() * 4) == dstPixelArray->length());
    m_context->readPixels(0, 0, newContextSize.width(), newContextSize.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, dstPixelArray->data());

    return true;
}
void FEDisplacementMap::applySoftware()
{
    FilterEffect* in = inputEffect(0);
    FilterEffect* in2 = inputEffect(1);

    ASSERT(m_xChannelSelector != CHANNEL_UNKNOWN);
    ASSERT(m_yChannelSelector != CHANNEL_UNKNOWN);

    Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult();
    if (!dstPixelArray)
        return;

    IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
    RefPtr<Uint8ClampedArray> srcPixelArrayA = in->asPremultipliedImage(effectADrawingRect);

    IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
    RefPtr<Uint8ClampedArray> srcPixelArrayB = in2->asUnmultipliedImage(effectBDrawingRect);

    ASSERT(srcPixelArrayA->length() == srcPixelArrayB->length());

    Filter* filter = this->filter();
    IntSize paintSize = absolutePaintRect().size();
    float scaleX = filter->applyHorizontalScale(m_scale);
    float scaleY = filter->applyVerticalScale(m_scale);
    float scaleForColorX = scaleX / 255.0;
    float scaleForColorY = scaleY / 255.0;
    float scaledOffsetX = 0.5 - scaleX * 0.5;
    float scaledOffsetY = 0.5 - scaleY * 0.5;
    int stride = paintSize.width() * 4;
    for (int y = 0; y < paintSize.height(); ++y) {
        int line = y * stride;
        for (int x = 0; x < paintSize.width(); ++x) {
            int dstIndex = line + x * 4;
            int srcX = x + static_cast<int>(scaleForColorX * srcPixelArrayB->item(dstIndex + m_xChannelSelector - 1) + scaledOffsetX);
            int srcY = y + static_cast<int>(scaleForColorY * srcPixelArrayB->item(dstIndex + m_yChannelSelector - 1) + scaledOffsetY);
            for (unsigned channel = 0; channel < 4; ++channel) {
                if (srcX < 0 || srcX >= paintSize.width() || srcY < 0 || srcY >= paintSize.height()) {
                    dstPixelArray->set(dstIndex + channel, static_cast<unsigned char>(0));
                } else {
                    unsigned char pixelValue = srcPixelArrayA->item(srcY * stride + srcX * 4 + channel);
                    dstPixelArray->set(dstIndex + channel, pixelValue);
                }
            }
        }
    }
}
Beispiel #7
0
void FETurbulence::platformApplySoftware()
{
    Uint8ClampedArray* pixelArray = createUnmultipliedImageResult();
    if (!pixelArray)
        return;

    if (absolutePaintRect().isEmpty()) {
        pixelArray->zeroFill();
        return;
    }

    PaintingData paintingData(m_seed, roundedIntSize(filterPrimitiveSubregion().size()));
    initPaint(paintingData);

    int optimalThreadNumber = (absolutePaintRect().width() * absolutePaintRect().height()) / s_minimalRectDimension;
    if (optimalThreadNumber > 1) {
        // Initialize parallel jobs
        WTF::ParallelJobs<FillRegionParameters> parallelJobs(&WebCore::FETurbulence::fillRegionWorker, optimalThreadNumber);

        // Fill the parameter array
        int i = parallelJobs.numberOfJobs();
        if (i > 1) {
            int startY = 0;
            int stepY = absolutePaintRect().height() / i;
            for (; i > 0; --i) {
                FillRegionParameters& params = parallelJobs.parameter(i-1);
                params.filter = this;
                params.pixelArray = pixelArray;
                params.paintingData = &paintingData;
                params.startY = startY;
                if (i != 1) {
                    params.endY = startY + stepY;
                    startY = startY + stepY;
                } else
                    params.endY = absolutePaintRect().height();
            }

            // Execute parallel jobs
            parallelJobs.execute();
            return;
        }
    }

    // Fallback to single threaded mode if there is no room for a new thread or the paint area is too small.
    fillRegion(pixelArray, paintingData, 0, absolutePaintRect().height());
}
Beispiel #8
0
inline void FEGaussianBlur::platformApplyGeneric(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize)
{
    int stride = 4 * paintSize.width();
    int dxLeft = 0;
    int dxRight = 0;
    int dyLeft = 0;
    int dyRight = 0;
    Uint8ClampedArray* src = srcPixelArray;
    Uint8ClampedArray* dst = tmpPixelArray;

    for (int i = 0; i < 3; ++i) {
        if (kernelSizeX) {
            kernelPosition(i, kernelSizeX, dxLeft, dxRight);
            boxBlur(src, dst, kernelSizeX, dxLeft, dxRight, 4, stride, paintSize.width(), paintSize.height(), isAlphaImage());
            swap(src, dst);
        }

        if (kernelSizeY) {
            kernelPosition(i, kernelSizeY, dyLeft, dyRight);
            boxBlur(src, dst, kernelSizeY, dyLeft, dyRight, stride, 4, paintSize.height(), paintSize.width(), isAlphaImage());
            swap(src, dst);
        }
    }

    // The final result should be stored in srcPixelArray.
    if (dst == srcPixelArray) {
        ASSERT(src->length() == dst->length());
        memcpy(dst->data(), src->data(), src->length());
    }

}
Beispiel #9
0
void FEMorphology::platformApplyGeneric(PaintingData* paintingData, int yStart, int yEnd)
{
    Uint8ClampedArray* srcPixelArray = paintingData->srcPixelArray;
    Uint8ClampedArray* dstPixelArray = paintingData->dstPixelArray;
    const int radiusX = paintingData->radiusX;
    const int radiusY = paintingData->radiusY;
    const int width = paintingData->width;
    const int height = paintingData->height;

    ASSERT(radiusX <= width || radiusY <= height);
    ASSERT(yStart >= 0 && yEnd <= height && yStart < yEnd);

    Vector<unsigned char> extrema;
    for (int y = yStart; y < yEnd; ++y) {
        int yStartExtrema = std::max(0, y - radiusY);
        int yEndExtrema = std::min(height - 1, y + radiusY);

        for (unsigned colorChannel = 0; colorChannel < 4; ++colorChannel) {
            extrema.clear();
            // Compute extremas for each columns
            for (int x = 0; x < radiusX; ++x)
                extrema.append(columnExtremum(srcPixelArray, x, yStartExtrema, yEndExtrema, width, colorChannel, m_type));

            // Kernel is filled, get extrema of next column
            for (int x = 0; x < width; ++x) {
                if (x < width - radiusX) {
                    int xEnd = std::min(x + radiusX, width - 1);
                    extrema.append(columnExtremum(srcPixelArray, xEnd, yStartExtrema, yEndExtrema + 1, width, colorChannel, m_type));
                }

                if (x > radiusX)
                    extrema.remove(0);

                // The extrema original size = radiusX.
                // Number of new addition = width - radiusX.
                // Number of removals = width - radiusX - 1.
                ASSERT(extrema.size() >= static_cast<size_t>(radiusX + 1));
                dstPixelArray->set(pixelArrayIndex(x, y, width, colorChannel), kernelExtremum(extrema, m_type));
            }
        }
    }
}
Beispiel #10
0
void FEMorphology::platformApplyGeneric(PaintingData* paintingData, int yStart, int yEnd)
{
    Uint8ClampedArray* srcPixelArray = paintingData->srcPixelArray;
    Uint8ClampedArray* dstPixelArray = paintingData->dstPixelArray;
    const int width = paintingData->width;
    const int height = paintingData->height;
    const int effectWidth = width * 4;
    const int radiusX = paintingData->radiusX;
    const int radiusY = paintingData->radiusY;

    Vector<unsigned char> extrema;
    for (int y = yStart; y < yEnd; ++y) {
        int extremaStartY = std::max(0, y - radiusY);
        int extremaEndY = std::min(height - 1, y + radiusY);
        for (unsigned int clrChannel = 0; clrChannel < 4; ++clrChannel) {
            extrema.clear();
            // Compute extremas for each columns
            for (int x = 0; x <= radiusX; ++x) {
                unsigned char columnExtrema = srcPixelArray->item(extremaStartY * effectWidth + 4 * x + clrChannel);
                for (int eY = extremaStartY + 1; eY < extremaEndY; ++eY) {
                    unsigned char pixel = srcPixelArray->item(eY * effectWidth + 4 * x + clrChannel);
                    if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && pixel <= columnExtrema)
                        || (m_type == FEMORPHOLOGY_OPERATOR_DILATE && pixel >= columnExtrema)) {
                        columnExtrema = pixel;
                    }
                }

                extrema.append(columnExtrema);
            }

            // Kernel is filled, get extrema of next column
            for (int x = 0; x < width; ++x) {
                const int endX = std::min(x + radiusX, width - 1);
                unsigned char columnExtrema = srcPixelArray->item(extremaStartY * effectWidth + endX * 4 + clrChannel);
                for (int i = extremaStartY + 1; i <= extremaEndY; ++i) {
                    unsigned char pixel = srcPixelArray->item(i * effectWidth + endX * 4 + clrChannel);
                    if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && pixel <= columnExtrema)
                        || (m_type == FEMORPHOLOGY_OPERATOR_DILATE && pixel >= columnExtrema))
                        columnExtrema = pixel;
                }
                if (x - radiusX >= 0)
                    extrema.remove(0);
                if (x + radiusX <= width)
                    extrema.append(columnExtrema);

                unsigned char entireExtrema = extrema[0];
                for (unsigned kernelIndex = 1; kernelIndex < extrema.size(); ++kernelIndex) {
                    if ((m_type == FEMORPHOLOGY_OPERATOR_ERODE && extrema[kernelIndex] <= entireExtrema)
                        || (m_type == FEMORPHOLOGY_OPERATOR_DILATE && extrema[kernelIndex] >= entireExtrema))
                        entireExtrema = extrema[kernelIndex];
                }
                dstPixelArray->set(y * effectWidth + 4 * x + clrChannel, entireExtrema);
            }
        }
    }
}
Beispiel #11
0
bool FEBlend::applySoftwareNEON()
{
    if (m_mode != WebBlendModeNormal
        && m_mode != WebBlendModeMultiply
        && m_mode != WebBlendModeScreen
        && m_mode != WebBlendModeDarken
        && m_mode != WebBlendModeLighten)
        return false;

    Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult();
    if (!dstPixelArray)
        return true;

    FilterEffect* in = inputEffect(0);
    FilterEffect* in2 = inputEffect(1);

    IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
    RefPtr<Uint8ClampedArray> srcPixelArrayA = in->asPremultipliedImage(effectADrawingRect);

    IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
    RefPtr<Uint8ClampedArray> srcPixelArrayB = in2->asPremultipliedImage(effectBDrawingRect);

    unsigned pixelArrayLength = srcPixelArrayA->length();
    ASSERT(pixelArrayLength == srcPixelArrayB->length());

    if (pixelArrayLength >= 8) {
        platformApplyNEON(srcPixelArrayA->data(), srcPixelArrayB->data(), dstPixelArray->data(), pixelArrayLength);
    } else {
        // If there is just one pixel we expand it to two.
        ASSERT(pixelArrayLength > 0);
        uint32_t sourceA[2] = {0, 0};
        uint32_t sourceBAndDest[2] = {0, 0};

        sourceA[0] = reinterpret_cast<uint32_t*>(srcPixelArrayA->data())[0];
        sourceBAndDest[0] = reinterpret_cast<uint32_t*>(srcPixelArrayB->data())[0];
        platformApplyNEON(reinterpret_cast<uint8_t*>(sourceA), reinterpret_cast<uint8_t*>(sourceBAndDest), reinterpret_cast<uint8_t*>(sourceBAndDest), 8);
        reinterpret_cast<uint32_t*>(dstPixelArray->data())[0] = sourceBAndDest[0];
    }
    return true;
}
void FEBlend::platformApplySoftware()
{
    FilterEffect* in = inputEffect(0);
    FilterEffect* in2 = inputEffect(1);

    ASSERT(m_mode > FEBLEND_MODE_UNKNOWN);
    ASSERT(m_mode <= FEBLEND_MODE_LIGHTEN);

    Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult();
    if (!dstPixelArray)
        return;

    IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
    RefPtr<Uint8ClampedArray> srcPixelArrayA = in->asPremultipliedImage(effectADrawingRect);

    IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
    RefPtr<Uint8ClampedArray> srcPixelArrayB = in2->asPremultipliedImage(effectBDrawingRect);

    unsigned pixelArrayLength = srcPixelArrayA->length();
    ASSERT(pixelArrayLength == srcPixelArrayB->length());

#if HAVE(ARM_NEON_INTRINSICS)
    if (pixelArrayLength >= 8)
        platformApplyNEON(srcPixelArrayA->data(), srcPixelArrayB->data(), dstPixelArray->data(), pixelArrayLength);
    else { // If there is just one pixel we expand it to two.
        ASSERT(pixelArrayLength > 0);
        uint32_t sourceA[2] = {0, 0};
        uint32_t sourceBAndDest[2] = {0, 0};

        sourceA[0] = reinterpret_cast<uint32_t*>(srcPixelArrayA->data())[0];
        sourceBAndDest[0] = reinterpret_cast<uint32_t*>(srcPixelArrayB->data())[0];
        platformApplyNEON(reinterpret_cast<uint8_t*>(sourceA), reinterpret_cast<uint8_t*>(sourceBAndDest), reinterpret_cast<uint8_t*>(sourceBAndDest), 8);
        reinterpret_cast<uint32_t*>(dstPixelArray->data())[0] = sourceBAndDest[0];
    }
#else
    platformApplyGeneric(srcPixelArrayA->data(), srcPixelArrayB->data(), dstPixelArray->data(), pixelArrayLength);
#endif
}
Beispiel #13
0
void FEComponentTransfer::platformApplySoftware()
{
    FilterEffect* in = inputEffect(0);

    Uint8ClampedArray* pixelArray = createUnmultipliedImageResult();
    if (!pixelArray)
        return;

    unsigned char rValues[256], gValues[256], bValues[256], aValues[256];
    getValues(rValues, gValues, bValues, aValues);
    unsigned char* tables[] = { rValues, gValues, bValues, aValues };

    IntRect drawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
    in->copyUnmultipliedImage(pixelArray, drawingRect);

    unsigned pixelArrayLength = pixelArray->length();
    for (unsigned pixelOffset = 0; pixelOffset < pixelArrayLength; pixelOffset += 4) {
        for (unsigned channel = 0; channel < 4; ++channel) {
            unsigned char c = pixelArray->item(pixelOffset + channel);
            pixelArray->set(pixelOffset + channel, tables[channel][c]);
        }
    }
}
Beispiel #14
0
bool FECustomFilter::applyShader()
{
    Uint8ClampedArray* dstPixelArray = createUnmultipliedImageResult();
    if (!dstPixelArray)
        return false;

    FilterEffect* in = inputEffect(0);
    IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
    RefPtr<Uint8ClampedArray> srcPixelArray = in->asUnmultipliedImage(effectDrawingRect);
    
    IntSize newContextSize(effectDrawingRect.size());
    bool hadContext = m_context;
    if (!m_context && !initializeContext())
        return false;
    m_context->makeContextCurrent();
    
    if (!hadContext || m_contextSize != newContextSize)
        resizeContext(newContextSize);

#if !PLATFORM(BLACKBERRY) // BlackBerry defines its own Texture class.
    // Do not draw the filter if the input image cannot fit inside a single GPU texture.
    if (m_inputTexture->tiles().numTilesX() != 1 || m_inputTexture->tiles().numTilesY() != 1)
        return false;
#endif
    
    // The shader had compiler errors. We cannot draw anything.
    if (!m_compiledProgram->isInitialized())
        return false;

    m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_frameBuffer);
    m_context->viewport(0, 0, newContextSize.width(), newContextSize.height());
    
    m_context->clearColor(0, 0, 0, 0);
    m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT);
    
    bindProgramAndBuffers(srcPixelArray.get());
    
    m_context->drawElements(GraphicsContext3D::TRIANGLES, m_mesh->indicesCount(), GraphicsContext3D::UNSIGNED_SHORT, 0);
    
    unbindVertexAttributes();

    ASSERT(static_cast<size_t>(newContextSize.width() * newContextSize.height() * 4) == dstPixelArray->length());
    m_context->readPixels(0, 0, newContextSize.width(), newContextSize.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, dstPixelArray->data());

    return true;
}
Beispiel #15
0
void FECustomFilter::platformApplySoftware()
{
    Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult();
    if (!dstPixelArray)
        return;

    FilterEffect* in = inputEffect(0);
    IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
    RefPtr<Uint8ClampedArray> srcPixelArray = in->asPremultipliedImage(effectDrawingRect);
    
    IntSize newContextSize(effectDrawingRect.size());
    bool hadContext = m_context;
    if (!m_context)
        initializeContext();
    
    if (!hadContext || m_contextSize != newContextSize)
        resizeContext(newContextSize);

    // Do not draw the filter if the input image cannot fit inside a single GPU texture.
    if (m_inputTexture->tiles().numTilesX() != 1 || m_inputTexture->tiles().numTilesY() != 1)
        return;
    
    // The shader had compiler errors. We cannot draw anything.
    if (!m_shader->isInitialized())
        return;

    m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_frameBuffer);
    m_context->viewport(0, 0, newContextSize.width(), newContextSize.height());
    
    m_context->clearColor(0, 0, 0, 0);
    m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT);
    
    bindProgramAndBuffers(srcPixelArray.get());
    
    m_context->drawElements(GraphicsContext3D::TRIANGLES, m_mesh->indicesCount(), GraphicsContext3D::UNSIGNED_SHORT, 0);
    
    ASSERT(static_cast<size_t>(newContextSize.width() * newContextSize.height() * 4) == dstPixelArray->length());
    m_context->readPixels(0, 0, newContextSize.width(), newContextSize.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, dstPixelArray->data());
}