1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/layers/d3d10/ContainerLayerD3D10.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,277 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "ContainerLayerD3D10.h" 1.10 + 1.11 +#include "ThebesLayerD3D10.h" 1.12 +#include "ReadbackProcessor.h" 1.13 + 1.14 +using namespace mozilla::gfx; 1.15 + 1.16 +namespace mozilla { 1.17 +namespace layers { 1.18 + 1.19 +ContainerLayerD3D10::ContainerLayerD3D10(LayerManagerD3D10 *aManager) 1.20 + : ContainerLayer(aManager, nullptr) 1.21 + , LayerD3D10(aManager) 1.22 +{ 1.23 + mImplData = static_cast<LayerD3D10*>(this); 1.24 +} 1.25 + 1.26 +ContainerLayerD3D10::~ContainerLayerD3D10() 1.27 +{ 1.28 + while (mFirstChild) { 1.29 + RemoveChild(mFirstChild); 1.30 + } 1.31 +} 1.32 + 1.33 +Layer* 1.34 +ContainerLayerD3D10::GetLayer() 1.35 +{ 1.36 + return this; 1.37 +} 1.38 + 1.39 +LayerD3D10* 1.40 +ContainerLayerD3D10::GetFirstChildD3D10() 1.41 +{ 1.42 + if (!mFirstChild) { 1.43 + return nullptr; 1.44 + } 1.45 + return static_cast<LayerD3D10*>(mFirstChild->ImplData()); 1.46 +} 1.47 + 1.48 +static inline LayerD3D10* 1.49 +GetNextSiblingD3D10(LayerD3D10* aLayer) 1.50 +{ 1.51 + Layer* layer = aLayer->GetLayer()->GetNextSibling(); 1.52 + return layer ? static_cast<LayerD3D10*>(layer-> 1.53 + ImplData()) 1.54 + : nullptr; 1.55 +} 1.56 + 1.57 +void 1.58 +ContainerLayerD3D10::RenderLayer() 1.59 +{ 1.60 + float renderTargetOffset[] = { 0, 0 }; 1.61 + 1.62 + nsIntRect visibleRect = mVisibleRegion.GetBounds(); 1.63 + float opacity = GetEffectiveOpacity(); 1.64 + bool useIntermediate = UseIntermediateSurface(); 1.65 + 1.66 + nsRefPtr<ID3D10RenderTargetView> previousRTView; 1.67 + nsRefPtr<ID3D10Texture2D> renderTexture; 1.68 + nsRefPtr<ID3D10RenderTargetView> rtView; 1.69 + float previousRenderTargetOffset[2]; 1.70 + nsIntSize previousViewportSize; 1.71 + 1.72 + gfx3DMatrix oldViewMatrix; 1.73 + 1.74 + if (useIntermediate) { 1.75 + device()->OMGetRenderTargets(1, getter_AddRefs(previousRTView), nullptr); 1.76 + 1.77 + D3D10_TEXTURE2D_DESC desc; 1.78 + memset(&desc, 0, sizeof(D3D10_TEXTURE2D_DESC)); 1.79 + desc.ArraySize = 1; 1.80 + desc.MipLevels = 1; 1.81 + desc.Width = visibleRect.width; 1.82 + desc.Height = visibleRect.height; 1.83 + desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; 1.84 + desc.SampleDesc.Count = 1; 1.85 + desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; 1.86 + HRESULT hr; 1.87 + hr = device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(renderTexture)); 1.88 + 1.89 + if (FAILED(hr)) { 1.90 + LayerManagerD3D10::ReportFailure(NS_LITERAL_CSTRING("Failed to create new texture for ContainerLayerD3D10!"), 1.91 + hr); 1.92 + return; 1.93 + } 1.94 + 1.95 + hr = device()->CreateRenderTargetView(renderTexture, nullptr, getter_AddRefs(rtView)); 1.96 + NS_ASSERTION(SUCCEEDED(hr), "Failed to create render target view for ContainerLayerD3D10!"); 1.97 + 1.98 + effect()->GetVariableByName("vRenderTargetOffset")-> 1.99 + GetRawValue(previousRenderTargetOffset, 0, 8); 1.100 + 1.101 + previousViewportSize = mD3DManager->GetViewport(); 1.102 + 1.103 + if (mVisibleRegion.GetNumRects() != 1 || !(GetContentFlags() & CONTENT_OPAQUE)) { 1.104 + Matrix4x4 transform3D = GetEffectiveTransform(); 1.105 + Matrix transform; 1.106 + // If we have an opaque ancestor layer, then we can be sure that 1.107 + // all the pixels we draw into are either opaque already or will be 1.108 + // covered by something opaque. Otherwise copying up the background is 1.109 + // not safe. 1.110 + if (mSupportsComponentAlphaChildren) { 1.111 + bool is2d = transform3D.Is2D(&transform); 1.112 + NS_ASSERTION(is2d, "Transform should be 2d when mSupportsComponentAlphaChildren."); 1.113 + 1.114 + // Copy background up from below. This applies any 2D transform that is 1.115 + // applied to use relative to our parent, and compensates for the offset 1.116 + // that was applied on our parent's rendering. 1.117 + D3D10_BOX srcBox; 1.118 + srcBox.left = std::max<int32_t>(visibleRect.x + int32_t(transform._31) - int32_t(previousRenderTargetOffset[0]), 0); 1.119 + srcBox.top = std::max<int32_t>(visibleRect.y + int32_t(transform._32) - int32_t(previousRenderTargetOffset[1]), 0); 1.120 + srcBox.right = std::min<int32_t>(srcBox.left + visibleRect.width, previousViewportSize.width); 1.121 + srcBox.bottom = std::min<int32_t>(srcBox.top + visibleRect.height, previousViewportSize.height); 1.122 + srcBox.back = 1; 1.123 + srcBox.front = 0; 1.124 + 1.125 + nsRefPtr<ID3D10Resource> srcResource; 1.126 + previousRTView->GetResource(getter_AddRefs(srcResource)); 1.127 + 1.128 + device()->CopySubresourceRegion(renderTexture, 0, 1.129 + 0, 0, 0, 1.130 + srcResource, 0, 1.131 + &srcBox); 1.132 + } else { 1.133 + float black[] = { 0, 0, 0, 0}; 1.134 + device()->ClearRenderTargetView(rtView, black); 1.135 + } 1.136 + } 1.137 + 1.138 + ID3D10RenderTargetView *rtViewPtr = rtView; 1.139 + device()->OMSetRenderTargets(1, &rtViewPtr, nullptr); 1.140 + 1.141 + renderTargetOffset[0] = (float)visibleRect.x; 1.142 + renderTargetOffset[1] = (float)visibleRect.y; 1.143 + effect()->GetVariableByName("vRenderTargetOffset")-> 1.144 + SetRawValue(renderTargetOffset, 0, 8); 1.145 + 1.146 + mD3DManager->SetViewport(nsIntSize(visibleRect.Size())); 1.147 + } 1.148 + 1.149 + D3D10_RECT oldD3D10Scissor; 1.150 + UINT numRects = 1; 1.151 + device()->RSGetScissorRects(&numRects, &oldD3D10Scissor); 1.152 + // Convert scissor to an nsIntRect. D3D10_RECT's are exclusive 1.153 + // on the bottom and right values. 1.154 + nsIntRect oldScissor(oldD3D10Scissor.left, 1.155 + oldD3D10Scissor.top, 1.156 + oldD3D10Scissor.right - oldD3D10Scissor.left, 1.157 + oldD3D10Scissor.bottom - oldD3D10Scissor.top); 1.158 + 1.159 + nsAutoTArray<Layer*, 12> children; 1.160 + SortChildrenBy3DZOrder(children); 1.161 + 1.162 + /* 1.163 + * Render this container's contents. 1.164 + */ 1.165 + for (uint32_t i = 0; i < children.Length(); i++) { 1.166 + LayerD3D10* layerToRender = static_cast<LayerD3D10*>(children.ElementAt(i)->ImplData()); 1.167 + 1.168 + if (layerToRender->GetLayer()->GetEffectiveVisibleRegion().IsEmpty()) { 1.169 + continue; 1.170 + } 1.171 + 1.172 + nsIntRect scissorRect = 1.173 + layerToRender->GetLayer()->CalculateScissorRect(oldScissor, nullptr); 1.174 + if (scissorRect.IsEmpty()) { 1.175 + continue; 1.176 + } 1.177 + 1.178 + D3D10_RECT d3drect; 1.179 + d3drect.left = scissorRect.x; 1.180 + d3drect.top = scissorRect.y; 1.181 + d3drect.right = scissorRect.x + scissorRect.width; 1.182 + d3drect.bottom = scissorRect.y + scissorRect.height; 1.183 + device()->RSSetScissorRects(1, &d3drect); 1.184 + 1.185 + layerToRender->RenderLayer(); 1.186 + } 1.187 + 1.188 + device()->RSSetScissorRects(1, &oldD3D10Scissor); 1.189 + 1.190 + if (useIntermediate) { 1.191 + mD3DManager->SetViewport(previousViewportSize); 1.192 + ID3D10RenderTargetView *rtView = previousRTView; 1.193 + device()->OMSetRenderTargets(1, &rtView, nullptr); 1.194 + effect()->GetVariableByName("vRenderTargetOffset")-> 1.195 + SetRawValue(previousRenderTargetOffset, 0, 8); 1.196 + 1.197 + SetEffectTransformAndOpacity(); 1.198 + 1.199 + ID3D10EffectTechnique *technique; 1.200 + if (LoadMaskTexture()) { 1.201 + if (GetTransform().CanDraw2D()) { 1.202 + technique = SelectShader(SHADER_RGBA | SHADER_PREMUL | SHADER_MASK); 1.203 + } else { 1.204 + technique = SelectShader(SHADER_RGBA | SHADER_PREMUL | SHADER_MASK_3D); 1.205 + } 1.206 + } else { 1.207 + technique = SelectShader(SHADER_RGBA | SHADER_PREMUL | SHADER_NO_MASK); 1.208 + } 1.209 + 1.210 + effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector( 1.211 + ShaderConstantRectD3D10( 1.212 + (float)visibleRect.x, 1.213 + (float)visibleRect.y, 1.214 + (float)visibleRect.width, 1.215 + (float)visibleRect.height) 1.216 + ); 1.217 + 1.218 + technique->GetPassByIndex(0)->Apply(0); 1.219 + 1.220 + ID3D10ShaderResourceView *view; 1.221 + device()->CreateShaderResourceView(renderTexture, nullptr, &view); 1.222 + device()->PSSetShaderResources(0, 1, &view); 1.223 + device()->Draw(4, 0); 1.224 + view->Release(); 1.225 + } 1.226 +} 1.227 + 1.228 +void 1.229 +ContainerLayerD3D10::LayerManagerDestroyed() 1.230 +{ 1.231 + while (mFirstChild) { 1.232 + GetFirstChildD3D10()->LayerManagerDestroyed(); 1.233 + RemoveChild(mFirstChild); 1.234 + } 1.235 +} 1.236 + 1.237 +void 1.238 +ContainerLayerD3D10::Validate() 1.239 +{ 1.240 + nsIntRect visibleRect = mVisibleRegion.GetBounds(); 1.241 + 1.242 + mSupportsComponentAlphaChildren = false; 1.243 + 1.244 + if (UseIntermediateSurface()) { 1.245 + Matrix4x4 transform3D = GetEffectiveTransform(); 1.246 + Matrix transform; 1.247 + 1.248 + if (mVisibleRegion.GetNumRects() == 1 && (GetContentFlags() & CONTENT_OPAQUE)) { 1.249 + // don't need a background, we're going to paint all opaque stuff 1.250 + mSupportsComponentAlphaChildren = true; 1.251 + } else { 1.252 + if (HasOpaqueAncestorLayer(this) && 1.253 + transform3D.Is2D(&transform) && !ThebesMatrix(transform).HasNonIntegerTranslation() && 1.254 + GetParent()->GetEffectiveVisibleRegion().GetBounds().Contains(visibleRect)) 1.255 + { 1.256 + // In this case we can copy up the background. See RenderLayer. 1.257 + mSupportsComponentAlphaChildren = true; 1.258 + } 1.259 + } 1.260 + } else { 1.261 + mSupportsComponentAlphaChildren = (GetContentFlags() & CONTENT_OPAQUE) || 1.262 + (mParent && mParent->SupportsComponentAlphaChildren()); 1.263 + } 1.264 + 1.265 + ReadbackProcessor readback; 1.266 + readback.BuildUpdates(this); 1.267 + 1.268 + Layer *layer = GetFirstChild(); 1.269 + while (layer) { 1.270 + if (layer->GetType() == TYPE_THEBES) { 1.271 + static_cast<ThebesLayerD3D10*>(layer)->Validate(&readback); 1.272 + } else { 1.273 + static_cast<LayerD3D10*>(layer->ImplData())->Validate(); 1.274 + } 1.275 + layer = layer->GetNextSibling(); 1.276 + } 1.277 +} 1.278 + 1.279 +} /* layers */ 1.280 +} /* mozilla */