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, ¶meters, &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; }