PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect, CoordinateSystem coordinateSystem) const
{
    if (context().isAcceleratedContext())
        flushContext();

    IntRect srcRect = rect;
    if (coordinateSystem == LogicalCoordinateSystem)
        srcRect.scale(m_resolutionScale);

    return m_data.getData(srcRect, internalSize(), context().isAcceleratedContext(), false, 1);
}
void LegacyCACFLayerTreeHost::resize()
{
    if (!m_d3dDevice)
        return;

    // Resetting the device might fail here. But that's OK, because if it does it we will attempt to
    // reset the device the next time we try to render.
    resetDevice(ChangedWindowSize);

    if (rootLayer()) {
        rootLayer()->setBounds(bounds());
        flushContext();
    }
}
void WKCACFViewLayerTreeHost::updateViewIfNeeded()
{
    if (!m_viewNeedsUpdate)
        return;
    m_viewNeedsUpdate = false;

    CGRect layerBounds = rootLayer()->bounds();

    CGRect bounds = this->bounds();
    WKCACFViewUpdate(m_view.get(), window(), &bounds);

    if (CGRectEqualToRect(layerBounds, rootLayer()->bounds()))
        return;

    // Flush the context so the layer's rendered bounds will match our bounds.
    flushContext();
}
void CACFLayerTreeHost::flushPendingLayerChangesNow()
{
    // Calling out to the client could cause our last reference to go away.
    RefPtr<CACFLayerTreeHost> protector(this);

    m_isFlushingLayerChanges = true;

    // Flush changes stored up in GraphicsLayers to their underlying PlatformCALayers, if
    // requested.
    if (m_client && m_shouldFlushPendingGraphicsLayerChanges) {
        m_shouldFlushPendingGraphicsLayerChanges = false;
        m_client->flushPendingGraphicsLayerChanges();
    }

    // Flush changes stored up in PlatformCALayers to the context so they will be rendered.
    flushContext();

    m_isFlushingLayerChanges = false;
}
String ImageBuffer::toDataURL(const String& mimeType, const double* quality, CoordinateSystem) const
{
    ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));

    if (context().isAcceleratedContext())
        flushContext();

    RetainPtr<CFStringRef> uti = utiFromMIMEType(mimeType);
    ASSERT(uti);

    RefPtr<Uint8ClampedArray> premultipliedData;
    RetainPtr<CGImageRef> image;

    if (CFEqual(uti.get(), jpegUTI())) {
        // JPEGs don't have an alpha channel, so we have to manually composite on top of black.
        premultipliedData = getPremultipliedImageData(IntRect(IntPoint(0, 0), logicalSize()));
        if (!premultipliedData)
            return "data:,";

        RetainPtr<CGDataProviderRef> dataProvider;
        dataProvider = adoptCF(CGDataProviderCreateWithData(0, premultipliedData->data(), 4 * logicalSize().width() * logicalSize().height(), 0));
        if (!dataProvider)
            return "data:,";

        image = adoptCF(CGImageCreate(logicalSize().width(), logicalSize().height(), 8, 32, 4 * logicalSize().width(),
                                    deviceRGBColorSpaceRef(), kCGBitmapByteOrderDefault | kCGImageAlphaNoneSkipLast,
                                    dataProvider.get(), 0, false, kCGRenderingIntentDefault));
    } else if (m_resolutionScale == 1) {
        image = copyNativeImage(CopyBackingStore);
        image = createCroppedImageIfNecessary(image.get(), internalSize());
    } else {
        image = copyNativeImage(DontCopyBackingStore);
        RetainPtr<CGContextRef> context = adoptCF(CGBitmapContextCreate(0, logicalSize().width(), logicalSize().height(), 8, 4 * logicalSize().width(), deviceRGBColorSpaceRef(), kCGImageAlphaPremultipliedLast));
        CGContextSetBlendMode(context.get(), kCGBlendModeCopy);
        CGContextClipToRect(context.get(), CGRectMake(0, 0, logicalSize().width(), logicalSize().height()));
        FloatSize imageSizeInUserSpace = scaleSizeToUserSpace(logicalSize(), m_data.backingStoreSize, internalSize());
        CGContextDrawImage(context.get(), CGRectMake(0, 0, imageSizeInUserSpace.width(), imageSizeInUserSpace.height()), image.get());
        image = adoptCF(CGBitmapContextCreateImage(context.get()));
    }

    return CGImageToDataURL(image.get(), mimeType, quality);
}
bool LegacyCACFLayerTreeHost::createRenderer()
{
    if (m_d3dDevice || !m_mightBeAbleToCreateDeviceLater)
        return m_d3dDevice;

    m_mightBeAbleToCreateDeviceLater = false;
    D3DPRESENT_PARAMETERS parameters = initialPresentationParameters();

    if (!d3d() || !::IsWindow(window()))
        return false;

    // D3D doesn't like to make back buffers for 0 size windows. We skirt this problem if we make the
    // passed backbuffer width and height non-zero. The window will necessarily get set to a non-zero
    // size eventually, and then the backbuffer size will get reset.
    RECT rect;
    GetClientRect(window(), &rect);

    if (rect.left-rect.right == 0 || rect.bottom-rect.top == 0) {
        parameters.BackBufferWidth = 1;
        parameters.BackBufferHeight = 1;
    }

    D3DCAPS9 d3dCaps;
    if (FAILED(d3d()->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps)))
        return false;

    DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE;
    if ((d3dCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) && d3dCaps.VertexProcessingCaps)
        behaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
    else
        behaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;

    COMPtr<IDirect3DDevice9> device;
    if (FAILED(d3d()->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window(), behaviorFlags, &parameters, &device))) {
        // In certain situations (e.g., shortly after waking from sleep), Direct3DCreate9() will
        // return an IDirect3D9 for which IDirect3D9::CreateDevice will always fail. In case we
        // have one of these bad IDirect3D9s, get rid of it so we'll fetch a new one the next time
        // we want to call CreateDevice.
        s_d3d->Release();
        s_d3d = 0;

        // Even if we don't have a bad IDirect3D9, in certain situations (e.g., shortly after
        // waking from sleep), CreateDevice will fail, but will later succeed if called again.
        m_mightBeAbleToCreateDeviceLater = true;

        return false;
    }

    // Now that we've created the IDirect3DDevice9 based on the capabilities we
    // got from the IDirect3D9 global object, we requery the device for its
    // actual capabilities. The capabilities returned by the device can
    // sometimes be more complete, for example when using software vertex
    // processing.
    D3DCAPS9 deviceCaps;
    if (FAILED(device->GetDeviceCaps(&deviceCaps)))
        return false;

    if (!hardwareCapabilitiesIndicateCoreAnimationSupport(deviceCaps))
        return false;

    m_d3dDevice = device;

    initD3DGeometry();

    wkCACFContextSetD3DDevice(m_context, m_d3dDevice.get());

    if (IsWindow(window())) {
        rootLayer()->setBounds(bounds());
        flushContext();
    }

    return true;
}