bool SVGImage::dataChanged(bool allDataReceived) { TRACE_EVENT0("blink", "SVGImage::dataChanged"); // Don't do anything if is an empty image. if (!data()->size()) return true; if (allDataReceived) { // SVGImage will fire events (and the default C++ handlers run) but doesn't // actually allow script to run so it's fine to call into it. We allow this // since it means an SVG data url can synchronously load like other image // types. EventDispatchForbiddenScope::AllowUserAgentEvents allowUserAgentEvents; DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<FrameLoaderClient>, dummyFrameLoaderClient, (EmptyFrameLoaderClient::create())); if (m_page) { toLocalFrame(m_page->mainFrame())->loader().load(FrameLoadRequest(0, blankURL(), SubstituteData(data(), AtomicString("image/svg+xml", AtomicString::ConstructFromLiteral), AtomicString("UTF-8", AtomicString::ConstructFromLiteral), KURL(), ForceSynchronousLoad))); return true; } Page::PageClients pageClients; fillWithEmptyClients(pageClients); m_chromeClient = SVGImageChromeClient::create(this); pageClients.chromeClient = m_chromeClient.get(); // FIXME: If this SVG ends up loading itself, we might leak the world. // The Cache code does not know about ImageResources holding Frames and // won't know to break the cycle. // This will become an issue when SVGImage will be able to load other // SVGImage objects, but we're safe now, because SVGImage can only be // loaded by a top-level document. OwnPtrWillBeRawPtr<Page> page; { TRACE_EVENT0("blink", "SVGImage::dataChanged::createPage"); page = adoptPtrWillBeNoop(new Page(pageClients)); page->settings().setScriptEnabled(false); page->settings().setPluginsEnabled(false); page->settings().setAcceleratedCompositingEnabled(false); // Because this page is detached, it can't get default font settings // from the embedder. Copy over font settings so we have sensible // defaults. These settings are fixed and will not update if changed. if (!Page::ordinaryPages().isEmpty()) { Settings& defaultSettings = (*Page::ordinaryPages().begin())->settings(); page->settings().genericFontFamilySettings() = defaultSettings.genericFontFamilySettings(); page->settings().setMinimumFontSize(defaultSettings.minimumFontSize()); page->settings().setMinimumLogicalFontSize(defaultSettings.minimumLogicalFontSize()); page->settings().setDefaultFontSize(defaultSettings.defaultFontSize()); page->settings().setDefaultFixedFontSize(defaultSettings.defaultFixedFontSize()); } } RefPtrWillBeRawPtr<LocalFrame> frame = nullptr; { TRACE_EVENT0("blink", "SVGImage::dataChanged::createFrame"); frame = LocalFrame::create(dummyFrameLoaderClient.get(), &page->frameHost(), 0); frame->setView(FrameView::create(frame.get())); frame->init(); } FrameLoader& loader = frame->loader(); loader.forceSandboxFlags(SandboxAll); frame->view()->setScrollbarsSuppressed(true); frame->view()->setCanHaveScrollbars(false); // SVG Images will always synthesize a viewBox, if it's not available, and thus never see scrollbars. frame->view()->setTransparent(true); // SVG Images are transparent. m_page = page.release(); TRACE_EVENT0("blink", "SVGImage::dataChanged::load"); loader.load(FrameLoadRequest(0, blankURL(), SubstituteData(data(), AtomicString("image/svg+xml", AtomicString::ConstructFromLiteral), AtomicString("UTF-8", AtomicString::ConstructFromLiteral), KURL(), ForceSynchronousLoad))); // Set the intrinsic size before a container size is available. m_intrinsicSize = containerSize(); } return m_page; }
void SwapChain11::initPassThroughResources() { TRACE_EVENT0("gpu.angle", "SwapChain11::initPassThroughResources"); if (mRenderToBackBuffer) { // The passthrough resources aren't needed if we're rendering directly to the back buffer. return; } ID3D11Device *device = mRenderer->getDevice(); ASSERT(device != NULL); // Make sure our resources are all not allocated, when we create ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL); ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL); D3D11_BUFFER_DESC vbDesc; vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4; vbDesc.Usage = D3D11_USAGE_DYNAMIC; vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; vbDesc.MiscFlags = 0; vbDesc.StructureByteStride = 0; HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer"); D3D11_SAMPLER_DESC samplerDesc; samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; samplerDesc.MipLODBias = 0.0f; samplerDesc.MaxAnisotropy = 0; samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; samplerDesc.BorderColor[0] = 0.0f; samplerDesc.BorderColor[1] = 0.0f; samplerDesc.BorderColor[2] = 0.0f; samplerDesc.BorderColor[3] = 0.0f; samplerDesc.MinLOD = 0; samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler"); D3D11_INPUT_ELEMENT_DESC quadLayout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), &mPassThroughIL); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout"); result = device->CreateVertexShader(g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), NULL, &mPassThroughVS); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader"); result = device->CreatePixelShader(g_PS_PassthroughRGBA2D, sizeof(g_PS_PassthroughRGBA2D), NULL, &mPassThroughPS); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader"); }
bool GrVkCopyManager::createCopyProgram(GrVkGpu* gpu) { TRACE_EVENT0("skia", TRACE_FUNC); const GrShaderCaps* shaderCaps = gpu->caps()->shaderCaps(); const char* version = shaderCaps->versionDeclString(); SkSL::String vertShaderText(version); vertShaderText.append( "#extension GL_ARB_separate_shader_objects : enable\n" "#extension GL_ARB_shading_language_420pack : enable\n" "layout(set = 0, binding = 0) uniform vertexUniformBuffer {" "half4 uPosXform;" "half4 uTexCoordXform;" "};" "layout(location = 0) in float2 inPosition;" "layout(location = 1) out half2 vTexCoord;" "// Copy Program VS\n" "void main() {" "vTexCoord = half2(inPosition * uTexCoordXform.xy + uTexCoordXform.zw);" "sk_Position.xy = inPosition * uPosXform.xy + uPosXform.zw;" "sk_Position.zw = half2(0, 1);" "}" ); SkSL::String fragShaderText(version); fragShaderText.append( "#extension GL_ARB_separate_shader_objects : enable\n" "#extension GL_ARB_shading_language_420pack : enable\n" "layout(set = 1, binding = 0) uniform sampler2D uTextureSampler;" "layout(location = 1) in half2 vTexCoord;" "// Copy Program FS\n" "void main() {" "sk_FragColor = texture(uTextureSampler, vTexCoord);" "}" ); SkSL::Program::Settings settings; SkSL::String spirv; SkSL::Program::Inputs inputs; if (!GrCompileVkShaderModule(gpu, vertShaderText, VK_SHADER_STAGE_VERTEX_BIT, &fVertShaderModule, &fShaderStageInfo[0], settings, &spirv, &inputs)) { this->destroyResources(gpu); return false; } SkASSERT(inputs.isEmpty()); if (!GrCompileVkShaderModule(gpu, fragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, &fFragShaderModule, &fShaderStageInfo[1], settings, &spirv, &inputs)) { this->destroyResources(gpu); return false; } SkASSERT(inputs.isEmpty()); VkDescriptorSetLayout dsLayout[2]; GrVkResourceProvider& resourceProvider = gpu->resourceProvider(); dsLayout[GrVkUniformHandler::kUniformBufferDescSet] = resourceProvider.getUniformDSLayout(); uint32_t samplerVisibility = kFragment_GrShaderFlag; SkTArray<uint32_t> visibilityArray(&samplerVisibility, 1); resourceProvider.getSamplerDescriptorSetHandle(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, visibilityArray, &fSamplerDSHandle); dsLayout[GrVkUniformHandler::kSamplerDescSet] = resourceProvider.getSamplerDSLayout(fSamplerDSHandle); // Create the VkPipelineLayout VkPipelineLayoutCreateInfo layoutCreateInfo; memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags)); layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; layoutCreateInfo.pNext = 0; layoutCreateInfo.flags = 0; layoutCreateInfo.setLayoutCount = 2; layoutCreateInfo.pSetLayouts = dsLayout; layoutCreateInfo.pushConstantRangeCount = 0; layoutCreateInfo.pPushConstantRanges = nullptr; VkPipelineLayout pipelineLayout; VkResult err = GR_VK_CALL(gpu->vkInterface(), CreatePipelineLayout(gpu->device(), &layoutCreateInfo, nullptr, &pipelineLayout)); if (err) { this->destroyResources(gpu); return false; } fPipelineLayout = new GrVkPipelineLayout(pipelineLayout); static const float vdata[] = { 0, 0, 0, 1, 1, 0, 1, 1 }; fVertexBuffer = GrVkVertexBuffer::Make(gpu, sizeof(vdata), false); SkASSERT(fVertexBuffer.get()); fVertexBuffer->updateData(vdata, sizeof(vdata)); // We use 2 float4's for uniforms fUniformBuffer.reset(GrVkUniformBuffer::Create(gpu, 8 * sizeof(float))); SkASSERT(fUniformBuffer.get()); return true; }
void CompositorMutatorImpl::registerProxyClient(CompositorProxyClientImpl* client) { TRACE_EVENT0("compositor-worker", "CompositorMutatorImpl::registerClient"); m_proxyClients.add(client); setNeedsMutate(); }
EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) { TRACE_EVENT0("gpu.angle", "SwapChain11::reset"); ID3D11Device *device = mRenderer->getDevice(); if (device == NULL) { return EGL_BAD_ACCESS; } // Release specific resources to free up memory for the new render target, while the // old render target still exists for the purpose of preserving its contents. SafeRelease(mSwapChain1); SafeRelease(mSwapChain); SafeRelease(mBackBufferTexture); SafeRelease(mBackBufferRTView); mSwapInterval = static_cast<unsigned int>(swapInterval); if (mSwapInterval > 4) { // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range return EGL_BAD_PARAMETER; } // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains if (backbufferWidth < 1 || backbufferHeight < 1) { releaseOffscreenTexture(); return EGL_SUCCESS; } if (mNativeWindow.getNativeWindow()) { const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat, mRenderer->getRenderer11DeviceCaps(), true); HRESULT result = mNativeWindow.createSwapChain(device, mRenderer->getDxgiFactory(), backbufferFormatInfo.texFormat, backbufferWidth, backbufferHeight, &mSwapChain); if (FAILED(result)) { ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); release(); if (d3d11::isDeviceLostError(result)) { return EGL_CONTEXT_LOST; } else { return EGL_BAD_ALLOC; } } if (mRenderer->getRenderer11DeviceCaps().supportsDXGI1_2) { mSwapChain1 = d3d11::DynamicCastComObject<IDXGISwapChain1>(mSwapChain); } result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture"); result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); } // If we are resizing the swap chain, we don't wish to recreate all the static resources if (!mPassThroughResourcesInit) { mPassThroughResourcesInit = true; initPassThroughResources(); } return resetOffscreenTexture(backbufferWidth, backbufferHeight); }
EGLint SwapChain11::resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight) { ASSERT(mNeedsOffscreenTexture); TRACE_EVENT0("gpu.angle", "SwapChain11::resetOffscreenTexture"); ID3D11Device *device = mRenderer->getDevice(); ASSERT(device != NULL); // D3D11 does not allow zero size textures ASSERT(backbufferWidth >= 1); ASSERT(backbufferHeight >= 1); // Preserve the render target content ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture; if (previousOffscreenTexture) { previousOffscreenTexture->AddRef(); } const int previousWidth = mWidth; const int previousHeight = mHeight; releaseOffscreenColorBuffer(); const d3d11::Format &backbufferFormatInfo = d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps()); // If the app passed in a share handle, open the resource // See EGL_ANGLE_d3d_share_handle_client_buffer if (mAppCreatedShareHandle) { ID3D11Resource *tempResource11; HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11); if (FAILED(result)) { ERR("Failed to open the swap chain pbuffer share handle: %08lX", result); release(); return EGL_BAD_PARAMETER; } result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture); SafeRelease(tempResource11); if (FAILED(result)) { ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result); release(); return EGL_BAD_PARAMETER; } // Validate offscreen texture parameters D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; mOffscreenTexture->GetDesc(&offscreenTextureDesc); if (offscreenTextureDesc.Width != (UINT)backbufferWidth || offscreenTextureDesc.Height != (UINT)backbufferHeight || offscreenTextureDesc.Format != backbufferFormatInfo.texFormat || offscreenTextureDesc.MipLevels != 1 || offscreenTextureDesc.ArraySize != 1) { ERR("Invalid texture parameters in the shared offscreen texture pbuffer"); release(); return EGL_BAD_PARAMETER; } } else { const bool useSharedResource = !mNativeWindow->getNativeWindow() && mRenderer->getShareHandleSupport(); D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; offscreenTextureDesc.Width = backbufferWidth; offscreenTextureDesc.Height = backbufferHeight; offscreenTextureDesc.Format = backbufferFormatInfo.texFormat; offscreenTextureDesc.MipLevels = 1; offscreenTextureDesc.ArraySize = 1; offscreenTextureDesc.SampleDesc.Count = 1; offscreenTextureDesc.SampleDesc.Quality = 0; offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT; offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; offscreenTextureDesc.CPUAccessFlags = 0; offscreenTextureDesc.MiscFlags = useSharedResource ? ANGLE_RESOURCE_SHARE_TYPE : 0; HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture); if (FAILED(result)) { ERR("Could not create offscreen texture: %08lX", result); release(); if (d3d11::isDeviceLostError(result)) { return EGL_CONTEXT_LOST; } else { return EGL_BAD_ALLOC; } } d3d11::SetDebugName(mOffscreenTexture, "Offscreen back buffer texture"); // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client if (useSharedResource) { IDXGIResource *offscreenTextureResource = NULL; result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource); // Fall back to no share handle on failure if (FAILED(result)) { ERR("Could not query offscreen texture resource: %08lX", result); } else { result = offscreenTextureResource->GetSharedHandle(&mShareHandle); SafeRelease(offscreenTextureResource); if (FAILED(result)) { mShareHandle = NULL; ERR("Could not get offscreen texture shared handle: %08lX", result); } } } } // This may return null if the original texture was created without a keyed mutex. mKeyedMutex = d3d11::DynamicCastComObject<IDXGIKeyedMutex>(mOffscreenTexture); D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc; offscreenRTVDesc.Format = backbufferFormatInfo.rtvFormat; offscreenRTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; offscreenRTVDesc.Texture2D.MipSlice = 0; HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, &offscreenRTVDesc, &mOffscreenRTView); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mOffscreenRTView, "Offscreen back buffer render target"); D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc; offscreenSRVDesc.Format = backbufferFormatInfo.srvFormat; offscreenSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; offscreenSRVDesc.Texture2D.MostDetailedMip = 0; offscreenSRVDesc.Texture2D.MipLevels = static_cast<UINT>(-1); result = device->CreateShaderResourceView(mOffscreenTexture, &offscreenSRVDesc, &mOffscreenSRView); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mOffscreenSRView, "Offscreen back buffer shader resource"); if (previousOffscreenTexture != nullptr) { D3D11_BOX sourceBox = {0}; sourceBox.left = 0; sourceBox.right = std::min(previousWidth, backbufferWidth); sourceBox.top = std::max(previousHeight - backbufferHeight, 0); sourceBox.bottom = previousHeight; sourceBox.front = 0; sourceBox.back = 1; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); const int yoffset = std::max(backbufferHeight - previousHeight, 0); deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox); SafeRelease(previousOffscreenTexture); if (mSwapChain) { swapRect(0, 0, backbufferWidth, backbufferHeight); } } return EGL_SUCCESS; }
EGLint SwapChain11::reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) { mSwapInterval = static_cast<unsigned int>(swapInterval); if (mSwapInterval > 4) { // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] // range return EGL_BAD_PARAMETER; } // If the swap chain already exists, just resize if (mSwapChain != nullptr) { return resize(backbufferWidth, backbufferHeight); } TRACE_EVENT0("gpu.angle", "SwapChain11::reset"); ID3D11Device *device = mRenderer->getDevice(); if (device == NULL) { return EGL_BAD_ACCESS; } // Release specific resources to free up memory for the new render target, while the // old render target still exists for the purpose of preserving its contents. SafeRelease(mSwapChain1); SafeRelease(mSwapChain); SafeRelease(mBackBufferTexture); SafeRelease(mBackBufferRTView); // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains if (backbufferWidth < 1 || backbufferHeight < 1) { releaseOffscreenColorBuffer(); return EGL_SUCCESS; } if (mNativeWindow->getNativeWindow()) { HRESULT result = mNativeWindow->createSwapChain(device, mRenderer->getDxgiFactory(), getSwapChainNativeFormat(), backbufferWidth, backbufferHeight, &mSwapChain); if (FAILED(result)) { ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); release(); if (d3d11::isDeviceLostError(result)) { return EGL_CONTEXT_LOST; } else { return EGL_BAD_ALLOC; } } if (mRenderer->getRenderer11DeviceCaps().supportsDXGI1_2) { mSwapChain1 = d3d11::DynamicCastComObject<IDXGISwapChain1>(mSwapChain); } result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture"); result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); result = device->CreateShaderResourceView(mBackBufferTexture, nullptr, &mBackBufferSRView); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mBackBufferSRView, "Back buffer shader resource view"); } mFirstSwap = true; return resetOffscreenBuffers(backbufferWidth, backbufferHeight); }
ResourcePtr<Resource> ResourceFetcher::requestResource(Resource::Type type, FetchRequest& request) { ASSERT(request.options().synchronousPolicy == RequestAsynchronously || type == Resource::Raw); TRACE_EVENT0("blink", "ResourceFetcher::requestResource"); KURL url = request.resourceRequest().url(); WTF_LOG(ResourceLoading, "ResourceFetcher::requestResource '%s', charset '%s', priority=%d, type=%s", url.elidedString().latin1().data(), request.charset().latin1().data(), request.priority(), ResourceTypeName(type)); // If only the fragment identifiers differ, it is the same resource. url = MemoryCache::removeFragmentIdentifierIfNeeded(url); if (!url.isValid()) return 0; if (!canRequest(type, url, request.options(), request.originRestriction())) return 0; if (LocalFrame* f = frame()) f->loaderClient()->dispatchWillRequestResource(&request); // See if we can use an existing resource from the cache. ResourcePtr<Resource> resource = memoryCache()->resourceForURL(url); const RevalidationPolicy policy = determineRevalidationPolicy(type, request, resource.get()); switch (policy) { case Reload: memoryCache()->remove(resource.get()); // Fall through case Load: resource = createResourceForLoading(type, request, request.charset()); break; case Revalidate: resource = createResourceForRevalidation(request, resource.get()); break; case Use: memoryCache()->updateForAccess(resource.get()); break; } if (!resource) return 0; if (!resource->hasClients()) m_deadStatsRecorder.update(policy); if (policy != Use) resource->setIdentifier(createUniqueIdentifier()); ResourceLoadPriority priority = loadPriority(type, request); if (priority != resource->resourceRequest().priority()) { resource->mutableResourceRequest().setPriority(priority); resource->didChangePriority(priority, 0); } if (resourceNeedsLoad(resource.get(), request, policy)) { if (!shouldLoadNewResource(type)) { if (memoryCache()->contains(resource.get())) memoryCache()->remove(resource.get()); return 0; } resource->load(this, request.options()); // For asynchronous loads that immediately fail, it's sufficient to return a // null Resource, as it indicates that something prevented the load from starting. // If there's a network error, that failure will happen asynchronously. However, if // a sync load receives a network error, it will have already happened by this point. // In that case, the requester should have access to the relevant ResourceError, so // we need to return a non-null Resource. if (resource->errorOccurred()) { if (memoryCache()->contains(resource.get())) memoryCache()->remove(resource.get()); return 0; } } requestLoadStarted(resource.get(), request, policy == Use ? ResourceLoadingFromCache : ResourceLoadingFromNetwork); ASSERT(resource->url() == url.string()); m_documentResources.set(resource->url(), resource); return resource; }
void Image::paintSkBitmap(GraphicsContext* context, const NativeImageSkia& bitmap, const SkRect& srcRect, const SkRect& destRect, const SkXfermode::Mode& compOp) { TRACE_EVENT0("skia", "paintSkBitmap"); SkPaint paint; paint.setXfermodeMode(compOp); paint.setAlpha(context->getNormalizedAlpha()); paint.setLooper(context->drawLooper()); // only antialias if we're rotated or skewed paint.setAntiAlias(hasNon90rotation(context)); ResamplingMode resampling; if (context->isAccelerated()) resampling = RESAMPLE_LINEAR; else if (context->printing()) resampling = RESAMPLE_NONE; else { // Take into account scale applied to the canvas when computing sampling mode (e.g. CSS scale or page scale). SkRect destRectTarget = destRect; if (!(context->getTotalMatrix().getType() & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask))) context->getTotalMatrix().mapRect(&destRectTarget, destRect); resampling = computeResamplingMode(context->getTotalMatrix(), bitmap, SkScalarToFloat(srcRect.width()), SkScalarToFloat(srcRect.height()), SkScalarToFloat(destRectTarget.width()), SkScalarToFloat(destRectTarget.height())); } if (resampling == RESAMPLE_NONE) { // FIXME: This is to not break tests (it results in the filter bitmap flag // being set to true). We need to decide if we respect RESAMPLE_NONE // being returned from computeResamplingMode. resampling = RESAMPLE_LINEAR; } resampling = limitResamplingMode(context, resampling); paint.setFilterBitmap(resampling == RESAMPLE_LINEAR); if (resampling == RESAMPLE_AWESOME) drawResampledBitmap(context, paint, bitmap, srcRect, destRect); else { // No resampling necessary, we can just draw the bitmap. We want to // filter it if we decided to do linear interpolation above, or if there // is something interesting going on with the matrix (like a rotation). // Note: for serialization, we will want to subset the bitmap first so // we don't send extra pixels. SkIRect enclosingSrcRect; SkRect enclosingDestRect; SkISize bitmapSize = SkISize::Make(bitmap.bitmap().width(), bitmap.bitmap().height()); bool needsClipping = computeBitmapDrawRects(bitmapSize, srcRect, destRect, &enclosingSrcRect, &enclosingDestRect); if (enclosingSrcRect.isEmpty() || enclosingDestRect.isEmpty()) return; // If destination is enlarged because source rectangle didn't align to // integer boundaries then we draw a slightly larger rectangle and clip // to the original destination rectangle. // See http://crbug.com/145540. if (needsClipping) { context->save(); context->clipRect(destRect); } context->drawBitmapRect(bitmap.bitmap(), &enclosingSrcRect, enclosingDestRect, &paint); if (needsClipping) context->restore(); } context->didDrawRect(destRect, paint, &bitmap.bitmap()); }
void ThreadState::visitStackRoots(Visitor* visitor) { TRACE_EVENT0("blink_gc", "ThreadState::visitStackRoots"); for (ThreadState* state : attachedThreads()) state->visitStack(visitor); }
void NativeImageSkia::draw(GraphicsContext* context, const SkRect& srcRect, const SkRect& destRect, PassRefPtr<SkXfermode> compOp) const { TRACE_EVENT0("skia", "NativeImageSkia::draw"); SkPaint paint; paint.setXfermode(compOp.get()); paint.setColorFilter(context->colorFilter()); paint.setAlpha(context->getNormalizedAlpha()); paint.setLooper(context->drawLooper()); // only antialias if we're rotated or skewed paint.setAntiAlias(hasNon90rotation(context)); ResamplingMode resampling; if (context->isAccelerated()) { resampling = LinearResampling; } else if (context->printing()) { resampling = NoResampling; } else { // Take into account scale applied to the canvas when computing sampling mode (e.g. CSS scale or page scale). SkRect destRectTarget = destRect; SkMatrix totalMatrix = context->getTotalMatrix(); if (!(totalMatrix.getType() & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask))) totalMatrix.mapRect(&destRectTarget, destRect); resampling = computeResamplingMode(totalMatrix, SkScalarToFloat(srcRect.width()), SkScalarToFloat(srcRect.height()), SkScalarToFloat(destRectTarget.width()), SkScalarToFloat(destRectTarget.height())); } if (resampling == NoResampling) { // FIXME: This is to not break tests (it results in the filter bitmap flag // being set to true). We need to decide if we respect NoResampling // being returned from computeResamplingMode. resampling = LinearResampling; } resampling = limitResamplingMode(context, resampling); paint.setFilterBitmap(resampling == LinearResampling); bool isLazyDecoded = DeferredImageDecoder::isLazyDecoded(bitmap()); // FIXME: Bicubic filtering in Skia is only applied to defer-decoded images // as an experiment. Once this filtering code path becomes stable we should // turn this on for all cases, including non-defer-decoded images. bool useBicubicFilter = resampling == AwesomeResampling && isLazyDecoded; if (useBicubicFilter) paint.setFilterLevel(SkPaint::kHigh_FilterLevel); if (resampling == AwesomeResampling && !useBicubicFilter) { // Resample the image and then draw the result to canvas with bilinear // filtering. drawResampledBitmap(context, paint, srcRect, destRect); } else { // We want to filter it if we decided to do interpolation above, or if // there is something interesting going on with the matrix (like a rotation). // Note: for serialization, we will want to subset the bitmap first so we // don't send extra pixels. context->drawBitmapRect(bitmap(), &srcRect, destRect, &paint); } if (isLazyDecoded) PlatformInstrumentation::didDrawLazyPixelRef(bitmap().getGenerationID()); context->didDrawRect(destRect, paint, &bitmap()); }
Clear11::Clear11(Renderer11 *renderer) : mRenderer(renderer), mClearBlendStates(StructLessThan<ClearBlendInfo>), mFloatClearShader(nullptr), mUintClearShader(nullptr), mIntClearShader(nullptr), mClearDepthStencilStates(StructLessThan<ClearDepthStencilInfo>), mVertexBuffer(nullptr), mRasterizerState(nullptr) { TRACE_EVENT0("gpu.angle", "Clear11::Clear11"); HRESULT result; ID3D11Device *device = renderer->getDevice(); D3D11_BUFFER_DESC vbDesc; vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex<float>) * 4; vbDesc.Usage = D3D11_USAGE_DYNAMIC; vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; vbDesc.MiscFlags = 0; vbDesc.StructureByteStride = 0; result = device->CreateBuffer(&vbDesc, nullptr, &mVertexBuffer); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mVertexBuffer, "Clear11 masked clear vertex buffer"); D3D11_RASTERIZER_DESC rsDesc; rsDesc.FillMode = D3D11_FILL_SOLID; rsDesc.CullMode = D3D11_CULL_NONE; rsDesc.FrontCounterClockwise = FALSE; rsDesc.DepthBias = 0; rsDesc.DepthBiasClamp = 0.0f; rsDesc.SlopeScaledDepthBias = 0.0f; rsDesc.DepthClipEnable = TRUE; rsDesc.ScissorEnable = FALSE; rsDesc.MultisampleEnable = FALSE; rsDesc.AntialiasedLineEnable = FALSE; result = device->CreateRasterizerState(&rsDesc, &mRasterizerState); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mRasterizerState, "Clear11 masked clear rasterizer state"); if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) { mFloatClearShader = new ClearShader(DXGI_FORMAT_R32G32B32A32_FLOAT, "Clear11 Float IL", g_VS_ClearFloat, ArraySize(g_VS_ClearFloat), "Clear11 Float VS", g_PS_ClearFloat_FL9, ArraySize(g_PS_ClearFloat_FL9), "Clear11 Float PS"); } else { mFloatClearShader = new ClearShader(DXGI_FORMAT_R32G32B32A32_FLOAT, "Clear11 Float IL", g_VS_ClearFloat, ArraySize(g_VS_ClearFloat), "Clear11 Float VS", g_PS_ClearFloat, ArraySize(g_PS_ClearFloat), "Clear11 Float PS"); } if (renderer->isES3Capable()) { mUintClearShader = new ClearShader(DXGI_FORMAT_R32G32B32A32_UINT, "Clear11 UINT IL", g_VS_ClearUint, ArraySize(g_VS_ClearUint), "Clear11 UINT VS", g_PS_ClearUint, ArraySize(g_PS_ClearUint), "Clear11 UINT PS"); mIntClearShader = new ClearShader(DXGI_FORMAT_R32G32B32A32_UINT, "Clear11 SINT IL", g_VS_ClearSint, ArraySize(g_VS_ClearSint), "Clear11 SINT VS", g_PS_ClearSint, ArraySize(g_PS_ClearSint), "Clear11 SINT PS"); } }
void PaintLayerCompositor::updateIfNeeded() { CompositingUpdateType updateType = m_pendingUpdateType; m_pendingUpdateType = CompositingUpdateNone; if (!hasAcceleratedCompositing()) { updateWithoutAcceleratedCompositing(updateType); return; } if (updateType == CompositingUpdateNone) return; PaintLayer* updateRoot = rootLayer(); Vector<PaintLayer*> layersNeedingPaintInvalidation; if (updateType >= CompositingUpdateAfterCompositingInputChange) { CompositingInputsUpdater(updateRoot).update(); #if ENABLE(ASSERT) // FIXME: Move this check to the end of the compositing update. CompositingInputsUpdater::assertNeedsCompositingInputsUpdateBitsCleared(updateRoot); #endif CompositingRequirementsUpdater(m_layoutView, m_compositingReasonFinder).update(updateRoot); CompositingLayerAssigner layerAssigner(this); layerAssigner.assign(updateRoot, layersNeedingPaintInvalidation); bool layersChanged = layerAssigner.layersChanged(); { TRACE_EVENT0("blink", "PaintLayerCompositor::updateAfterCompositingChange"); if (const FrameView::ScrollableAreaSet* scrollableAreas = m_layoutView.frameView()->scrollableAreas()) { for (ScrollableArea* scrollableArea : *scrollableAreas) layersChanged |= scrollableArea->updateAfterCompositingChange(); } } if (layersChanged) { updateType = std::max(updateType, CompositingUpdateRebuildTree); if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) scrollingCoordinator->notifyGeometryChanged(); } } if (updateType != CompositingUpdateNone) { if (RuntimeEnabledFeatures::compositorWorkerEnabled() && m_scrollLayer) { if (Element* scrollingElement = m_layoutView.document().scrollingElement()) { uint64_t elementId = 0; uint32_t mutableProperties = WebCompositorMutablePropertyNone; if (scrollingElement->hasCompositorProxy()) { elementId = DOMNodeIds::idForNode(scrollingElement); mutableProperties = (WebCompositorMutablePropertyScrollLeft | WebCompositorMutablePropertyScrollTop) & scrollingElement->compositorMutableProperties(); } m_scrollLayer->setElementId(elementId); m_scrollLayer->setCompositorMutableProperties(mutableProperties); } } GraphicsLayerUpdater updater; updater.update(*updateRoot, layersNeedingPaintInvalidation); if (updater.needsRebuildTree()) updateType = std::max(updateType, CompositingUpdateRebuildTree); #if ENABLE(ASSERT) // FIXME: Move this check to the end of the compositing update. GraphicsLayerUpdater::assertNeedsToUpdateGraphicsLayerBitsCleared(*updateRoot); #endif } if (updateType >= CompositingUpdateRebuildTree) { GraphicsLayerTreeBuilder::AncestorInfo ancestorInfo; GraphicsLayerVector childList; ancestorInfo.childLayersOfEnclosingCompositedLayer = &childList; { TRACE_EVENT0("blink", "GraphicsLayerTreeBuilder::rebuild"); GraphicsLayerTreeBuilder().rebuild(*updateRoot, ancestorInfo); } if (childList.isEmpty()) destroyRootLayer(); else m_rootContentLayer->setChildren(childList); applyOverlayFullscreenVideoAdjustmentIfNeeded(); } if (m_needsUpdateFixedBackground) { rootFixedBackgroundsChanged(); m_needsUpdateFixedBackground = false; } for (unsigned i = 0; i < layersNeedingPaintInvalidation.size(); i++) forceRecomputePaintInvalidationRectsIncludingNonCompositingDescendants(layersNeedingPaintInvalidation[i]->layoutObject()); m_layoutView.frameView()->setFrameTimingRequestsDirty(true); // Inform the inspector that the layer tree has changed. if (m_layoutView.frame()->isMainFrame()) InspectorInstrumentation::layerTreeDidChange(m_layoutView.frame()); }
void CompositorMutatorImpl::setNeedsMutate() { TRACE_EVENT0("compositor-worker", "CompositorMutatorImpl::setNeedsMutate"); m_client->setNeedsMutate(); }
gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile, const std::vector<CompileConfig> &configs, const D3D_SHADER_MACRO *overrideMacros, ID3DBlob **outCompiledBlob, std::string *outDebugInfo) { ASSERT(mInitialized); #if !defined(ANGLE_ENABLE_WINDOWS_STORE) ASSERT(mD3DCompilerModule); #endif ASSERT(mD3DCompileFunc); #if !defined(ANGLE_ENABLE_WINDOWS_STORE) if (gl::DebugAnnotationsActive()) { std::string sourcePath = getTempPath(); std::string sourceText = FormatString("#line 2 \"%s\"\n\n%s", sourcePath.c_str(), hlsl.c_str()); writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size()); } #endif const D3D_SHADER_MACRO *macros = overrideMacros ? overrideMacros : nullptr; for (size_t i = 0; i < configs.size(); ++i) { ID3DBlob *errorMessage = nullptr; ID3DBlob *binary = nullptr; HRESULT result = S_OK; { TRACE_EVENT0("gpu.angle", "D3DCompile"); SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.D3DCompileMS"); result = mD3DCompileFunc(hlsl.c_str(), hlsl.length(), gl::g_fakepath, macros, nullptr, "main", profile.c_str(), configs[i].flags, 0, &binary, &errorMessage); } if (errorMessage) { std::string message = reinterpret_cast<const char*>(errorMessage->GetBufferPointer()); SafeRelease(errorMessage); infoLog.appendSanitized(message.c_str()); TRACE("\n%s", hlsl.c_str()); TRACE("\n%s", message.c_str()); if ((message.find("error X3531:") != std::string::npos || // "can't unroll loops marked with loop attribute" message.find("error X4014:") != std::string::npos) && // "cannot have gradient operations inside loops with divergent flow control", // even though it is counter-intuitive to disable unrolling for this error, // some very long shaders have trouble deciding which loops to unroll and // turning off forced unrolls allows them to compile properly. macros != nullptr) { macros = nullptr; // Disable [loop] and [flatten] // Retry without changing compiler flags i--; continue; } } if (SUCCEEDED(result)) { *outCompiledBlob = binary; (*outDebugInfo) += "// COMPILER INPUT HLSL BEGIN\n\n" + hlsl + "\n// COMPILER INPUT HLSL END\n"; #if ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED (*outDebugInfo) += "\n\n// ASSEMBLY BEGIN\n\n"; (*outDebugInfo) += "// Compiler configuration: " + configs[i].name + "\n// Flags:\n"; for (size_t fIx = 0; fIx < ArraySize(CompilerFlagInfos); ++fIx) { if (IsCompilerFlagSet(configs[i].flags, CompilerFlagInfos[fIx].mFlag)) { (*outDebugInfo) += std::string("// ") + CompilerFlagInfos[fIx].mName + "\n"; } } (*outDebugInfo) += "// Macros:\n"; if (macros == nullptr) { (*outDebugInfo) += "// - : -\n"; } else { for (const D3D_SHADER_MACRO *mIt = macros; mIt->Name != nullptr; ++mIt) { (*outDebugInfo) += std::string("// ") + mIt->Name + " : " + mIt->Definition + "\n"; } } std::string disassembly; ANGLE_TRY(disassembleBinary(binary, &disassembly)); (*outDebugInfo) += "\n" + disassembly + "\n// ASSEMBLY END\n"; #endif // ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED return gl::NoError(); } if (result == E_OUTOFMEMORY) { *outCompiledBlob = nullptr; return gl::Error(GL_OUT_OF_MEMORY, "HLSL compiler had an unexpected failure, result: 0x%X.", result); } infoLog << "Warning: D3D shader compilation failed with " << configs[i].name << " flags. (" << profile << ")"; if (i + 1 < configs.size()) { infoLog << " Retrying with " << configs[i + 1].name; } } // None of the configurations succeeded in compiling this shader but the compiler is still intact *outCompiledBlob = nullptr; return gl::NoError(); }
void Image::drawPattern(GraphicsContext* context, const FloatRect& floatSrcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator compositeOp, const FloatRect& destRect, BlendMode blendMode) { TRACE_EVENT0("skia", "Image::drawPattern"); RefPtr<NativeImageSkia> bitmap = nativeImageForCurrentFrame(); if (!bitmap) return; FloatRect normSrcRect = adjustForNegativeSize(floatSrcRect); normSrcRect.intersect(FloatRect(0, 0, bitmap->bitmap().width(), bitmap->bitmap().height())); if (destRect.isEmpty() || normSrcRect.isEmpty()) return; // nothing to draw SkMatrix ctm = context->getTotalMatrix(); SkMatrix totalMatrix; totalMatrix.setConcat(ctm, patternTransform); // Figure out what size the bitmap will be in the destination. The // destination rect is the bounds of the pattern, we need to use the // matrix to see how big it will be. SkRect destRectTarget; totalMatrix.mapRect(&destRectTarget, normSrcRect); float destBitmapWidth = SkScalarToFloat(destRectTarget.width()); float destBitmapHeight = SkScalarToFloat(destRectTarget.height()); // Compute the resampling mode. ResamplingMode resampling; if (context->isAccelerated() || context->printing()) resampling = RESAMPLE_LINEAR; else resampling = computeResamplingMode(totalMatrix, *bitmap, normSrcRect.width(), normSrcRect.height(), destBitmapWidth, destBitmapHeight); resampling = limitResamplingMode(context, resampling); // Load the transform WebKit requested. SkMatrix matrix(patternTransform); SkShader* shader; if (resampling == RESAMPLE_AWESOME) { // Do nice resampling. float scaleX = destBitmapWidth / normSrcRect.width(); float scaleY = destBitmapHeight / normSrcRect.height(); SkRect scaledSrcRect; SkIRect enclosingScaledSrcRect; // The image fragment generated here is not exactly what is // requested. The scale factor used is approximated and image // fragment is slightly larger to align to integer // boundaries. SkBitmap resampled = extractScaledImageFragment(*bitmap, normSrcRect, scaleX, scaleY, &scaledSrcRect, &enclosingScaledSrcRect); shader = SkShader::CreateBitmapShader(resampled, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); // Since we just resized the bitmap, we need to remove the scale // applied to the pixels in the bitmap shader. This means we need // CTM * patternTransform to have identity scale. Since we // can't modify CTM (or the rectangle will be drawn in the wrong // place), we must set patternTransform's scale to the inverse of // CTM scale. matrix.setScaleX(ctm.getScaleX() ? 1 / ctm.getScaleX() : 1); matrix.setScaleY(ctm.getScaleY() ? 1 / ctm.getScaleY() : 1); } else { // No need to do nice resampling. SkBitmap srcSubset; bitmap->bitmap().extractSubset(&srcSubset, enclosingIntRect(normSrcRect)); shader = SkShader::CreateBitmapShader(srcSubset, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); } // We also need to translate it such that the origin of the pattern is the // origin of the destination rect, which is what WebKit expects. Skia uses // the coordinate system origin as the base for the patter. If WebKit wants // a shifted image, it will shift it from there using the patternTransform. float adjustedX = phase.x() + normSrcRect.x() * narrowPrecisionToFloat(patternTransform.a()); float adjustedY = phase.y() + normSrcRect.y() * narrowPrecisionToFloat(patternTransform.d()); matrix.postTranslate(SkFloatToScalar(adjustedX), SkFloatToScalar(adjustedY)); shader->setLocalMatrix(matrix); SkPaint paint; paint.setShader(shader)->unref(); paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp, blendMode)); paint.setFilterBitmap(resampling == RESAMPLE_LINEAR); context->drawRect(destRect, paint); }
GrGLProgram* GrGLProgramBuilder::finalize() { TRACE_EVENT0("skia", TRACE_FUNC); // verify we can get a program id GrGLuint programID; GL_CALL_RET(programID, CreateProgram()); if (0 == programID) { this->cleanupFragmentProcessors(); return nullptr; } if (this->gpu()->glCaps().programBinarySupport() && this->gpu()->getContext()->contextPriv().getPersistentCache()) { GL_CALL(ProgramParameteri(programID, GR_GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GR_GL_TRUE)); } this->finalizeShaders(); // compile shaders and bind attributes / uniforms const GrPrimitiveProcessor& primProc = this->primitiveProcessor(); SkSL::Program::Settings settings; settings.fCaps = this->gpu()->glCaps().shaderCaps(); settings.fFlipY = this->pipeline().proxy()->origin() != kTopLeft_GrSurfaceOrigin; settings.fSharpenTextures = this->gpu()->getContext()->contextPriv().sharpenMipmappedTextures(); settings.fFragColorIsInOut = this->fragColorIsInOut(); SkSL::Program::Inputs inputs; SkTDArray<GrGLuint> shadersToDelete; bool cached = fGpu->glCaps().programBinarySupport() && nullptr != fCached.get(); if (cached) { this->bindProgramResourceLocations(programID); // cache hit, just hand the binary to GL const uint8_t* bytes = fCached->bytes(); size_t offset = 0; memcpy(&inputs, bytes + offset, sizeof(inputs)); offset += sizeof(inputs); int binaryFormat; memcpy(&binaryFormat, bytes + offset, sizeof(binaryFormat)); offset += sizeof(binaryFormat); GrGLClearErr(this->gpu()->glInterface()); GR_GL_CALL_NOERRCHECK(this->gpu()->glInterface(), ProgramBinary(programID, binaryFormat, (void*) (bytes + offset), fCached->size() - offset)); if (GR_GL_GET_ERROR(this->gpu()->glInterface()) == GR_GL_NO_ERROR) { if (inputs.fRTHeight) { this->addRTHeightUniform(SKSL_RTHEIGHT_NAME); } cached = this->checkLinkStatus(programID); } else { cached = false; } } if (!cached) { // cache miss, compile shaders if (fFS.fForceHighPrecision) { settings.fForceHighPrecision = true; } SkSL::String glsl; std::unique_ptr<SkSL::Program> fs = GrSkSLtoGLSL(gpu()->glContext(), GR_GL_FRAGMENT_SHADER, fFS.fCompilerStrings.begin(), fFS.fCompilerStringLengths.begin(), fFS.fCompilerStrings.count(), settings, &glsl); inputs = fs->fInputs; if (inputs.fRTHeight) { this->addRTHeightUniform(SKSL_RTHEIGHT_NAME); } if (!this->compileAndAttachShaders(glsl.c_str(), glsl.size(), programID, GR_GL_FRAGMENT_SHADER, &shadersToDelete, settings, inputs)) { this->cleanupProgram(programID, shadersToDelete); return nullptr; } std::unique_ptr<SkSL::Program> vs = GrSkSLtoGLSL(gpu()->glContext(), GR_GL_VERTEX_SHADER, fVS.fCompilerStrings.begin(), fVS.fCompilerStringLengths.begin(), fVS.fCompilerStrings.count(), settings, &glsl); if (!this->compileAndAttachShaders(glsl.c_str(), glsl.size(), programID, GR_GL_VERTEX_SHADER, &shadersToDelete, settings, inputs)) { this->cleanupProgram(programID, shadersToDelete); return nullptr; } // NVPR actually requires a vertex shader to compile bool useNvpr = primProc.isPathRendering(); if (!useNvpr) { int vaCount = primProc.numAttribs(); for (int i = 0; i < vaCount; i++) { GL_CALL(BindAttribLocation(programID, i, primProc.getAttrib(i).fName)); } } if (primProc.willUseGeoShader()) { std::unique_ptr<SkSL::Program> gs; gs = GrSkSLtoGLSL(gpu()->glContext(), GR_GL_GEOMETRY_SHADER, fGS.fCompilerStrings.begin(), fGS.fCompilerStringLengths.begin(), fGS.fCompilerStrings.count(), settings, &glsl); if (!this->compileAndAttachShaders(glsl.c_str(), glsl.size(), programID, GR_GL_GEOMETRY_SHADER, &shadersToDelete, settings, inputs)) { this->cleanupProgram(programID, shadersToDelete); return nullptr; } } this->bindProgramResourceLocations(programID); GL_CALL(LinkProgram(programID)); } // Calling GetProgramiv is expensive in Chromium. Assume success in release builds. bool checkLinked = kChromium_GrGLDriver != fGpu->ctxInfo().driver(); #ifdef SK_DEBUG checkLinked = true; #endif if (checkLinked) { if (!this->checkLinkStatus(programID)) { SkDebugf("VS:\n"); GrGLPrintShader(fGpu->glContext(), GR_GL_VERTEX_SHADER, fVS.fCompilerStrings.begin(), fVS.fCompilerStringLengths.begin(), fVS.fCompilerStrings.count(), settings); if (primProc.willUseGeoShader()) { SkDebugf("\nGS:\n"); GrGLPrintShader(fGpu->glContext(), GR_GL_GEOMETRY_SHADER, fGS.fCompilerStrings.begin(), fGS.fCompilerStringLengths.begin(), fGS.fCompilerStrings.count(), settings); } SkDebugf("\nFS:\n"); GrGLPrintShader(fGpu->glContext(), GR_GL_FRAGMENT_SHADER, fFS.fCompilerStrings.begin(), fFS.fCompilerStringLengths.begin(), fFS.fCompilerStrings.count(), settings); SkDEBUGFAIL(""); return nullptr; } } this->resolveProgramResourceLocations(programID); this->cleanupShaders(shadersToDelete); if (!cached && this->gpu()->getContext()->contextPriv().getPersistentCache() && fGpu->glCaps().programBinarySupport()) { GrGLsizei length = 0; GL_CALL(GetProgramiv(programID, GL_PROGRAM_BINARY_LENGTH, &length)); if (length > 0) { // store shader in cache sk_sp<SkData> key = SkData::MakeWithoutCopy(desc()->asKey(), desc()->keyLength()); GrGLenum binaryFormat; std::unique_ptr<char[]> binary(new char[length]); GL_CALL(GetProgramBinary(programID, length, &length, &binaryFormat, binary.get())); size_t dataLength = sizeof(inputs) + sizeof(binaryFormat) + length; std::unique_ptr<uint8_t[]> data(new uint8_t[dataLength]); size_t offset = 0; memcpy(data.get() + offset, &inputs, sizeof(inputs)); offset += sizeof(inputs); memcpy(data.get() + offset, &binaryFormat, sizeof(binaryFormat)); offset += sizeof(binaryFormat); memcpy(data.get() + offset, binary.get(), length); this->gpu()->getContext()->contextPriv().getPersistentCache()->store( *key, *SkData::MakeWithoutCopy(data.get(), dataLength)); } } return this->createProgram(programID); }
void sortLayers(Vector<CCLayerImpl*>::iterator first, Vector<CCLayerImpl*>::iterator end, CCLayerSorter* layerSorter) { TRACE_EVENT0("cc", "LayerRendererChromium::sortLayers"); layerSorter->sort(first, end); }
EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) { TRACE_EVENT0("gpu.angle", "SwapChain11::resize"); ID3D11Device *device = mRenderer->getDevice(); if (device == NULL) { return EGL_BAD_ACCESS; } // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains if (backbufferWidth < 1 || backbufferHeight < 1) { return EGL_SUCCESS; } // Don't resize unnecessarily if (mWidth == backbufferWidth && mHeight == backbufferHeight) { return EGL_SUCCESS; } // Can only call resize if we have already created our swap buffer and resources ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView && mBackBufferSRView); SafeRelease(mBackBufferTexture); SafeRelease(mBackBufferRTView); SafeRelease(mBackBufferSRView); // Resize swap chain DXGI_SWAP_CHAIN_DESC desc; HRESULT result = mSwapChain->GetDesc(&desc); if (FAILED(result)) { ERR("Error reading swap chain description: 0x%08X", result); release(); return EGL_BAD_ALLOC; } result = mSwapChain->ResizeBuffers(desc.BufferCount, backbufferWidth, backbufferHeight, getSwapChainNativeFormat(), 0); if (FAILED(result)) { ERR("Error resizing swap chain buffers: 0x%08X", result); release(); if (d3d11::isDeviceLostError(result)) { return EGL_CONTEXT_LOST; } else { return EGL_BAD_ALLOC; } } result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); ASSERT(SUCCEEDED(result)); if (SUCCEEDED(result)) { d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture"); result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); ASSERT(SUCCEEDED(result)); if (SUCCEEDED(result)) { d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); } result = device->CreateShaderResourceView(mBackBufferTexture, nullptr, &mBackBufferSRView); ASSERT(SUCCEEDED(result)); if (SUCCEEDED(result)) { d3d11::SetDebugName(mBackBufferSRView, "Back buffer shader resource"); } } mFirstSwap = true; return resetOffscreenBuffers(backbufferWidth, backbufferHeight); }
// Create a new environment and setup the global object. // // The global object corresponds to a DOMWindow instance. However, to // allow properties of the JS DOMWindow instance to be shadowed, we // use a shadow object as the global object and use the JS DOMWindow // instance as the prototype for that shadow object. The JS DOMWindow // instance is undetectable from JavaScript code because the __proto__ // accessors skip that object. // // The shadow object and the DOMWindow instance are seen as one object // from JavaScript. The JavaScript object that corresponds to a // DOMWindow instance is the shadow object. When mapping a DOMWindow // instance to a V8 object, we return the shadow object. // // To implement split-window, see // 1) https://bugs.webkit.org/show_bug.cgi?id=17249 // 2) https://wiki.mozilla.org/Gecko:SplitWindow // 3) https://bugzilla.mozilla.org/show_bug.cgi?id=296639 // we need to split the shadow object further into two objects: // an outer window and an inner window. The inner window is the hidden // prototype of the outer window. The inner window is the default // global object of the context. A variable declared in the global // scope is a property of the inner window. // // The outer window sticks to a Frame, it is exposed to JavaScript // via window.window, window.self, window.parent, etc. The outer window // has a security token which is the domain. The outer window cannot // have its own properties. window.foo = 'x' is delegated to the // inner window. // // When a frame navigates to a new page, the inner window is cut off // the outer window, and the outer window identify is preserved for // the frame. However, a new inner window is created for the new page. // If there are JS code holds a closure to the old inner window, // it won't be able to reach the outer window via its global object. bool V8WindowShell::initializeIfNeeded() { if (m_contextHolder) return true; TRACE_EVENT0("v8", "V8WindowShell::initializeIfNeeded"); v8::HandleScope handleScope(m_isolate); createContext(); if (!m_contextHolder) return false; v8::Handle<v8::Context> context = m_contextHolder->context(); V8PerContextDataHolder::install(context); m_world->setIsolatedWorldField(context); bool isMainWorld = m_world->isMainWorld(); v8::Context::Scope contextScope(context); if (m_global.isEmpty()) { m_global.set(m_isolate, context->Global()); if (m_global.isEmpty()) { disposeContext(DoNotDetachGlobal); return false; } } if (!isMainWorld) { V8WindowShell* mainWindow = m_frame->script().existingWindowShell(mainThreadNormalWorld()); if (mainWindow && !mainWindow->context().IsEmpty()) setInjectedScriptContextDebugId(context, m_frame->script().contextDebugId(mainWindow->context())); } m_perContextData = V8PerContextData::create(context); if (!m_perContextData->init()) { disposeContext(DoNotDetachGlobal); return false; } m_perContextData->setActivityLogger(DOMWrapperWorld::activityLogger(m_world->worldId())); if (!installDOMWindow()) { disposeContext(DoNotDetachGlobal); return false; } if (isMainWorld) { updateDocument(); setSecurityToken(); if (m_frame->document()) { ContentSecurityPolicy* csp = m_frame->document()->contentSecurityPolicy(); context->AllowCodeGenerationFromStrings(csp->allowEval(0, ContentSecurityPolicy::SuppressReport)); context->SetErrorMessageForCodeGenerationFromStrings(v8String(m_isolate, csp->evalDisabledErrorMessage())); } } else { // Using the default security token means that the canAccess is always // called, which is slow. // FIXME: Use tokens where possible. This will mean keeping track of all // created contexts so that they can all be updated when the // document domain // changes. context->UseDefaultSecurityToken(); SecurityOrigin* origin = m_world->isolatedWorldSecurityOrigin(); if (origin && InspectorInstrumentation::hasFrontends()) { ScriptState* scriptState = ScriptState::forContext(v8::Local<v8::Context>::New(m_isolate, context)); InspectorInstrumentation::didCreateIsolatedContext(m_frame, scriptState, origin); } } m_frame->loader().client()->didCreateScriptContext(context, m_world->extensionGroup(), m_world->worldId()); return true; }
void SwapChain11::initPassThroughResources() { if (mPassThroughResourcesInit) { return; } TRACE_EVENT0("gpu.angle", "SwapChain11::initPassThroughResources"); ID3D11Device *device = mRenderer->getDevice(); ASSERT(device != NULL); // Make sure our resources are all not allocated, when we create ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL); ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL); D3D11_BUFFER_DESC vbDesc; vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4; vbDesc.Usage = D3D11_USAGE_DYNAMIC; vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; vbDesc.MiscFlags = 0; vbDesc.StructureByteStride = 0; HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer"); D3D11_SAMPLER_DESC samplerDesc; samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; samplerDesc.MipLODBias = 0.0f; samplerDesc.MaxAnisotropy = 0; samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; samplerDesc.BorderColor[0] = 0.0f; samplerDesc.BorderColor[1] = 0.0f; samplerDesc.BorderColor[2] = 0.0f; samplerDesc.BorderColor[3] = 0.0f; samplerDesc.MinLOD = 0; samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler"); D3D11_INPUT_ELEMENT_DESC quadLayout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), &mPassThroughIL); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout"); result = device->CreateVertexShader(g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), NULL, &mPassThroughVS); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader"); result = device->CreatePixelShader(g_PS_PassthroughRGBA2D, sizeof(g_PS_PassthroughRGBA2D), NULL, &mPassThroughPS); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader"); // Use the default rasterizer state but without culling D3D11_RASTERIZER_DESC rasterizerDesc; rasterizerDesc.FillMode = D3D11_FILL_SOLID; rasterizerDesc.CullMode = D3D11_CULL_NONE; rasterizerDesc.FrontCounterClockwise = FALSE; rasterizerDesc.DepthBias = 0; rasterizerDesc.SlopeScaledDepthBias = 0.0f; rasterizerDesc.DepthBiasClamp = 0.0f; rasterizerDesc.DepthClipEnable = TRUE; rasterizerDesc.ScissorEnable = FALSE; rasterizerDesc.MultisampleEnable = FALSE; rasterizerDesc.AntialiasedLineEnable = FALSE; result = device->CreateRasterizerState(&rasterizerDesc, &mPassThroughRS); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mPassThroughRS, "Swap chain pass through rasterizer state"); mPassThroughResourcesInit = true; }
Error Display::initialize() { // Re-initialize default platform if it's needed InitDefaultPlatformImpl(); SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.DisplayInitializeMS"); TRACE_EVENT0("gpu.angle", "egl::Display::initialize"); ASSERT(mImplementation != nullptr); if (isInitialized()) { return Error(EGL_SUCCESS); } Error error = mImplementation->initialize(this); if (error.isError()) { // Log extended error message here std::stringstream errorStream; errorStream << "ANGLE Display::initialize error " << error.getID() << ": " << error.getMessage(); ANGLEPlatformCurrent()->logError(errorStream.str().c_str()); return error; } mCaps = mImplementation->getCaps(); mConfigSet = mImplementation->generateConfigs(); if (mConfigSet.size() == 0) { mImplementation->terminate(); return Error(EGL_NOT_INITIALIZED); } initDisplayExtensions(); initVendorString(); // Populate the Display's EGLDeviceEXT if the Display wasn't created using one if (mPlatform != EGL_PLATFORM_DEVICE_EXT) { if (mDisplayExtensions.deviceQuery) { rx::DeviceImpl *impl = nullptr; error = mImplementation->getDevice(&impl); if (error.isError()) { return error; } error = Device::CreateDevice(this, impl, &mDevice); if (error.isError()) { return error; } } else { mDevice = nullptr; } } else { // For EGL_PLATFORM_DEVICE_EXT, mDevice should always be populated using // an external device ASSERT(mDevice != nullptr); } mInitialized = true; return Error(EGL_SUCCESS); }