예제 #1
0
ImageData* ImageData::create(unsigned width,
                             unsigned height,
                             ExceptionState& exceptionState) {
  if (!width || !height) {
    exceptionState.throwDOMException(
        IndexSizeError, String::format("The source %s is zero or not a number.",
                                       width ? "height" : "width"));
    return nullptr;
  }

  CheckedNumeric<unsigned> dataSize = 4;
  dataSize *= width;
  dataSize *= height;
  if (!dataSize.IsValid() || static_cast<int>(width) < 0 ||
      static_cast<int>(height) < 0) {
    exceptionState.throwDOMException(
        IndexSizeError,
        "The requested image size exceeds the supported range.");
    return nullptr;
  }

  DOMUint8ClampedArray* byteArray =
      DOMUint8ClampedArray::createOrNull(dataSize.ValueOrDie());
  if (!byteArray) {
    exceptionState.throwDOMException(V8Error,
                                     "Out of memory at ImageData creation");
    return nullptr;
  }

  return new ImageData(IntSize(width, height), byteArray);
}
예제 #2
0
ImageData* ImageData::create(const IntSize& size,
                             DOMUint8ClampedArray* byteArray) {
  CheckedNumeric<int> dataSize = 4;
  dataSize *= size.width();
  dataSize *= size.height();
  if (!dataSize.IsValid())
    return nullptr;

  if (dataSize.ValueOrDie() < 0 ||
      static_cast<unsigned>(dataSize.ValueOrDie()) > byteArray->length())
    return nullptr;

  return new ImageData(size, byteArray);
}
예제 #3
0
ImageData* ImageData::create(const IntSize& size) {
  CheckedNumeric<int> dataSize = 4;
  dataSize *= size.width();
  dataSize *= size.height();
  if (!dataSize.IsValid() || dataSize.ValueOrDie() < 0)
    return nullptr;

  DOMUint8ClampedArray* byteArray =
      DOMUint8ClampedArray::createOrNull(dataSize.ValueOrDie());
  if (!byteArray)
    return nullptr;

  return new ImageData(size, byteArray);
}
예제 #4
0
bool ImageBuffer::getImageData(Multiply multiplied, const IntRect& rect, WTF::ArrayBufferContents& contents) const
{
    CheckedNumeric<int> dataSize = 4;
    dataSize *= rect.width();
    dataSize *= rect.height();
    if (!dataSize.IsValid())
        return false;

    if (!isSurfaceValid()) {
        size_t allocSizeInBytes = rect.width() * rect.height() * 4;
        void* data;
        WTF::ArrayBufferContents::allocateMemoryOrNull(allocSizeInBytes, WTF::ArrayBufferContents::ZeroInitialize, data);
        if (!data)
            return false;
        WTF::ArrayBufferContents result(data, allocSizeInBytes, WTF::ArrayBufferContents::NotShared);
        result.transfer(contents);
        return true;
    }

    DCHECK(canvas());
    RefPtr<SkImage> snapshot = m_surface->newImageSnapshot(PreferNoAcceleration, SnapshotReasonGetImageData);
    if (!snapshot)
        return false;

    const bool mayHaveStrayArea =
        m_surface->isAccelerated() // GPU readback may fail silently
        || rect.x() < 0
        || rect.y() < 0
        || rect.maxX() > m_surface->size().width()
        || rect.maxY() > m_surface->size().height();
    size_t allocSizeInBytes = rect.width() * rect.height() * 4;
    void* data;
    WTF::ArrayBufferContents::InitializationPolicy initializationPolicy = mayHaveStrayArea ? WTF::ArrayBufferContents::ZeroInitialize : WTF::ArrayBufferContents::DontInitialize;
    WTF::ArrayBufferContents::allocateMemoryOrNull(allocSizeInBytes, initializationPolicy, data);
    if (!data)
        return false;
    WTF::ArrayBufferContents result(data, allocSizeInBytes, WTF::ArrayBufferContents::NotShared);

    SkAlphaType alphaType = (multiplied == Premultiplied) ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
    SkImageInfo info = SkImageInfo::Make(rect.width(), rect.height(), kRGBA_8888_SkColorType, alphaType);

    snapshot->readPixels(info, result.data(), 4 * rect.width(), rect.x(), rect.y());
    result.transfer(contents);
    return true;
}
예제 #5
0
void ImageBuffer::updateGPUMemoryUsage() const
{
    if (this->isAccelerated()) {
        // If image buffer is accelerated, we should keep track of GPU memory usage.
        int gpuBufferCount = 2;
        CheckedNumeric<intptr_t> checkedGPUUsage = 4 * gpuBufferCount;
        checkedGPUUsage *= this->size().width();
        checkedGPUUsage *= this->size().height();
        intptr_t gpuMemoryUsage = checkedGPUUsage.ValueOrDefault(std::numeric_limits<intptr_t>::max());

        if (!m_gpuMemoryUsage) // was not accelerated before
            s_globalAcceleratedImageBufferCount++;

        s_globalGPUMemoryUsage += (gpuMemoryUsage - m_gpuMemoryUsage);
        m_gpuMemoryUsage = gpuMemoryUsage;
    } else if (m_gpuMemoryUsage) {
        // In case of switching from accelerated to non-accelerated mode,
        // the GPU memory usage needs to be updated too.
        DCHECK_GT(s_globalAcceleratedImageBufferCount, 0u);
        s_globalAcceleratedImageBufferCount--;
        s_globalGPUMemoryUsage -= m_gpuMemoryUsage;
        m_gpuMemoryUsage = 0;
    }
}
예제 #6
0
bool DrawingBuffer::paintRenderingResultsToImageData(int& width, int& height, SourceDrawingBuffer sourceBuffer, WTF::ArrayBufferContents& contents)
{
    ASSERT(!m_premultipliedAlpha);
    width = size().width();
    height = size().height();

    CheckedNumeric<int> dataSize = 4;
    dataSize *= width;
    dataSize *= height;
    if (!dataSize.IsValid())
        return false;

    WTF::ArrayBufferContents pixels(width * height, 4, WTF::ArrayBufferContents::NotShared, WTF::ArrayBufferContents::DontInitialize);

    GLuint fbo = 0;
    if (sourceBuffer == FrontBuffer && m_frontColorBuffer.texInfo.textureId) {
        m_gl->GenFramebuffers(1, &fbo);
        m_gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
        m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_frontColorBuffer.texInfo.parameters.target, m_frontColorBuffer.texInfo.textureId, 0);
    } else {
        m_gl->BindFramebuffer(GL_FRAMEBUFFER, framebuffer());
    }

    readBackFramebuffer(static_cast<unsigned char*>(pixels.data()), width, height, ReadbackRGBA, WebGLImageConversion::AlphaDoNothing);
    flipVertically(static_cast<uint8_t*>(pixels.data()), width, height);

    if (fbo) {
        m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_frontColorBuffer.texInfo.parameters.target, 0, 0);
        m_gl->DeleteFramebuffers(1, &fbo);
    }

    restoreFramebufferBindings();

    pixels.transfer(contents);
    return true;
}