gfx/layers/d3d10/ContainerLayerD3D10.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
michael@0 2 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "ContainerLayerD3D10.h"
michael@0 7
michael@0 8 #include "ThebesLayerD3D10.h"
michael@0 9 #include "ReadbackProcessor.h"
michael@0 10
michael@0 11 using namespace mozilla::gfx;
michael@0 12
michael@0 13 namespace mozilla {
michael@0 14 namespace layers {
michael@0 15
michael@0 16 ContainerLayerD3D10::ContainerLayerD3D10(LayerManagerD3D10 *aManager)
michael@0 17 : ContainerLayer(aManager, nullptr)
michael@0 18 , LayerD3D10(aManager)
michael@0 19 {
michael@0 20 mImplData = static_cast<LayerD3D10*>(this);
michael@0 21 }
michael@0 22
michael@0 23 ContainerLayerD3D10::~ContainerLayerD3D10()
michael@0 24 {
michael@0 25 while (mFirstChild) {
michael@0 26 RemoveChild(mFirstChild);
michael@0 27 }
michael@0 28 }
michael@0 29
michael@0 30 Layer*
michael@0 31 ContainerLayerD3D10::GetLayer()
michael@0 32 {
michael@0 33 return this;
michael@0 34 }
michael@0 35
michael@0 36 LayerD3D10*
michael@0 37 ContainerLayerD3D10::GetFirstChildD3D10()
michael@0 38 {
michael@0 39 if (!mFirstChild) {
michael@0 40 return nullptr;
michael@0 41 }
michael@0 42 return static_cast<LayerD3D10*>(mFirstChild->ImplData());
michael@0 43 }
michael@0 44
michael@0 45 static inline LayerD3D10*
michael@0 46 GetNextSiblingD3D10(LayerD3D10* aLayer)
michael@0 47 {
michael@0 48 Layer* layer = aLayer->GetLayer()->GetNextSibling();
michael@0 49 return layer ? static_cast<LayerD3D10*>(layer->
michael@0 50 ImplData())
michael@0 51 : nullptr;
michael@0 52 }
michael@0 53
michael@0 54 void
michael@0 55 ContainerLayerD3D10::RenderLayer()
michael@0 56 {
michael@0 57 float renderTargetOffset[] = { 0, 0 };
michael@0 58
michael@0 59 nsIntRect visibleRect = mVisibleRegion.GetBounds();
michael@0 60 float opacity = GetEffectiveOpacity();
michael@0 61 bool useIntermediate = UseIntermediateSurface();
michael@0 62
michael@0 63 nsRefPtr<ID3D10RenderTargetView> previousRTView;
michael@0 64 nsRefPtr<ID3D10Texture2D> renderTexture;
michael@0 65 nsRefPtr<ID3D10RenderTargetView> rtView;
michael@0 66 float previousRenderTargetOffset[2];
michael@0 67 nsIntSize previousViewportSize;
michael@0 68
michael@0 69 gfx3DMatrix oldViewMatrix;
michael@0 70
michael@0 71 if (useIntermediate) {
michael@0 72 device()->OMGetRenderTargets(1, getter_AddRefs(previousRTView), nullptr);
michael@0 73
michael@0 74 D3D10_TEXTURE2D_DESC desc;
michael@0 75 memset(&desc, 0, sizeof(D3D10_TEXTURE2D_DESC));
michael@0 76 desc.ArraySize = 1;
michael@0 77 desc.MipLevels = 1;
michael@0 78 desc.Width = visibleRect.width;
michael@0 79 desc.Height = visibleRect.height;
michael@0 80 desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
michael@0 81 desc.SampleDesc.Count = 1;
michael@0 82 desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
michael@0 83 HRESULT hr;
michael@0 84 hr = device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(renderTexture));
michael@0 85
michael@0 86 if (FAILED(hr)) {
michael@0 87 LayerManagerD3D10::ReportFailure(NS_LITERAL_CSTRING("Failed to create new texture for ContainerLayerD3D10!"),
michael@0 88 hr);
michael@0 89 return;
michael@0 90 }
michael@0 91
michael@0 92 hr = device()->CreateRenderTargetView(renderTexture, nullptr, getter_AddRefs(rtView));
michael@0 93 NS_ASSERTION(SUCCEEDED(hr), "Failed to create render target view for ContainerLayerD3D10!");
michael@0 94
michael@0 95 effect()->GetVariableByName("vRenderTargetOffset")->
michael@0 96 GetRawValue(previousRenderTargetOffset, 0, 8);
michael@0 97
michael@0 98 previousViewportSize = mD3DManager->GetViewport();
michael@0 99
michael@0 100 if (mVisibleRegion.GetNumRects() != 1 || !(GetContentFlags() & CONTENT_OPAQUE)) {
michael@0 101 Matrix4x4 transform3D = GetEffectiveTransform();
michael@0 102 Matrix transform;
michael@0 103 // If we have an opaque ancestor layer, then we can be sure that
michael@0 104 // all the pixels we draw into are either opaque already or will be
michael@0 105 // covered by something opaque. Otherwise copying up the background is
michael@0 106 // not safe.
michael@0 107 if (mSupportsComponentAlphaChildren) {
michael@0 108 bool is2d = transform3D.Is2D(&transform);
michael@0 109 NS_ASSERTION(is2d, "Transform should be 2d when mSupportsComponentAlphaChildren.");
michael@0 110
michael@0 111 // Copy background up from below. This applies any 2D transform that is
michael@0 112 // applied to use relative to our parent, and compensates for the offset
michael@0 113 // that was applied on our parent's rendering.
michael@0 114 D3D10_BOX srcBox;
michael@0 115 srcBox.left = std::max<int32_t>(visibleRect.x + int32_t(transform._31) - int32_t(previousRenderTargetOffset[0]), 0);
michael@0 116 srcBox.top = std::max<int32_t>(visibleRect.y + int32_t(transform._32) - int32_t(previousRenderTargetOffset[1]), 0);
michael@0 117 srcBox.right = std::min<int32_t>(srcBox.left + visibleRect.width, previousViewportSize.width);
michael@0 118 srcBox.bottom = std::min<int32_t>(srcBox.top + visibleRect.height, previousViewportSize.height);
michael@0 119 srcBox.back = 1;
michael@0 120 srcBox.front = 0;
michael@0 121
michael@0 122 nsRefPtr<ID3D10Resource> srcResource;
michael@0 123 previousRTView->GetResource(getter_AddRefs(srcResource));
michael@0 124
michael@0 125 device()->CopySubresourceRegion(renderTexture, 0,
michael@0 126 0, 0, 0,
michael@0 127 srcResource, 0,
michael@0 128 &srcBox);
michael@0 129 } else {
michael@0 130 float black[] = { 0, 0, 0, 0};
michael@0 131 device()->ClearRenderTargetView(rtView, black);
michael@0 132 }
michael@0 133 }
michael@0 134
michael@0 135 ID3D10RenderTargetView *rtViewPtr = rtView;
michael@0 136 device()->OMSetRenderTargets(1, &rtViewPtr, nullptr);
michael@0 137
michael@0 138 renderTargetOffset[0] = (float)visibleRect.x;
michael@0 139 renderTargetOffset[1] = (float)visibleRect.y;
michael@0 140 effect()->GetVariableByName("vRenderTargetOffset")->
michael@0 141 SetRawValue(renderTargetOffset, 0, 8);
michael@0 142
michael@0 143 mD3DManager->SetViewport(nsIntSize(visibleRect.Size()));
michael@0 144 }
michael@0 145
michael@0 146 D3D10_RECT oldD3D10Scissor;
michael@0 147 UINT numRects = 1;
michael@0 148 device()->RSGetScissorRects(&numRects, &oldD3D10Scissor);
michael@0 149 // Convert scissor to an nsIntRect. D3D10_RECT's are exclusive
michael@0 150 // on the bottom and right values.
michael@0 151 nsIntRect oldScissor(oldD3D10Scissor.left,
michael@0 152 oldD3D10Scissor.top,
michael@0 153 oldD3D10Scissor.right - oldD3D10Scissor.left,
michael@0 154 oldD3D10Scissor.bottom - oldD3D10Scissor.top);
michael@0 155
michael@0 156 nsAutoTArray<Layer*, 12> children;
michael@0 157 SortChildrenBy3DZOrder(children);
michael@0 158
michael@0 159 /*
michael@0 160 * Render this container's contents.
michael@0 161 */
michael@0 162 for (uint32_t i = 0; i < children.Length(); i++) {
michael@0 163 LayerD3D10* layerToRender = static_cast<LayerD3D10*>(children.ElementAt(i)->ImplData());
michael@0 164
michael@0 165 if (layerToRender->GetLayer()->GetEffectiveVisibleRegion().IsEmpty()) {
michael@0 166 continue;
michael@0 167 }
michael@0 168
michael@0 169 nsIntRect scissorRect =
michael@0 170 layerToRender->GetLayer()->CalculateScissorRect(oldScissor, nullptr);
michael@0 171 if (scissorRect.IsEmpty()) {
michael@0 172 continue;
michael@0 173 }
michael@0 174
michael@0 175 D3D10_RECT d3drect;
michael@0 176 d3drect.left = scissorRect.x;
michael@0 177 d3drect.top = scissorRect.y;
michael@0 178 d3drect.right = scissorRect.x + scissorRect.width;
michael@0 179 d3drect.bottom = scissorRect.y + scissorRect.height;
michael@0 180 device()->RSSetScissorRects(1, &d3drect);
michael@0 181
michael@0 182 layerToRender->RenderLayer();
michael@0 183 }
michael@0 184
michael@0 185 device()->RSSetScissorRects(1, &oldD3D10Scissor);
michael@0 186
michael@0 187 if (useIntermediate) {
michael@0 188 mD3DManager->SetViewport(previousViewportSize);
michael@0 189 ID3D10RenderTargetView *rtView = previousRTView;
michael@0 190 device()->OMSetRenderTargets(1, &rtView, nullptr);
michael@0 191 effect()->GetVariableByName("vRenderTargetOffset")->
michael@0 192 SetRawValue(previousRenderTargetOffset, 0, 8);
michael@0 193
michael@0 194 SetEffectTransformAndOpacity();
michael@0 195
michael@0 196 ID3D10EffectTechnique *technique;
michael@0 197 if (LoadMaskTexture()) {
michael@0 198 if (GetTransform().CanDraw2D()) {
michael@0 199 technique = SelectShader(SHADER_RGBA | SHADER_PREMUL | SHADER_MASK);
michael@0 200 } else {
michael@0 201 technique = SelectShader(SHADER_RGBA | SHADER_PREMUL | SHADER_MASK_3D);
michael@0 202 }
michael@0 203 } else {
michael@0 204 technique = SelectShader(SHADER_RGBA | SHADER_PREMUL | SHADER_NO_MASK);
michael@0 205 }
michael@0 206
michael@0 207 effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
michael@0 208 ShaderConstantRectD3D10(
michael@0 209 (float)visibleRect.x,
michael@0 210 (float)visibleRect.y,
michael@0 211 (float)visibleRect.width,
michael@0 212 (float)visibleRect.height)
michael@0 213 );
michael@0 214
michael@0 215 technique->GetPassByIndex(0)->Apply(0);
michael@0 216
michael@0 217 ID3D10ShaderResourceView *view;
michael@0 218 device()->CreateShaderResourceView(renderTexture, nullptr, &view);
michael@0 219 device()->PSSetShaderResources(0, 1, &view);
michael@0 220 device()->Draw(4, 0);
michael@0 221 view->Release();
michael@0 222 }
michael@0 223 }
michael@0 224
michael@0 225 void
michael@0 226 ContainerLayerD3D10::LayerManagerDestroyed()
michael@0 227 {
michael@0 228 while (mFirstChild) {
michael@0 229 GetFirstChildD3D10()->LayerManagerDestroyed();
michael@0 230 RemoveChild(mFirstChild);
michael@0 231 }
michael@0 232 }
michael@0 233
michael@0 234 void
michael@0 235 ContainerLayerD3D10::Validate()
michael@0 236 {
michael@0 237 nsIntRect visibleRect = mVisibleRegion.GetBounds();
michael@0 238
michael@0 239 mSupportsComponentAlphaChildren = false;
michael@0 240
michael@0 241 if (UseIntermediateSurface()) {
michael@0 242 Matrix4x4 transform3D = GetEffectiveTransform();
michael@0 243 Matrix transform;
michael@0 244
michael@0 245 if (mVisibleRegion.GetNumRects() == 1 && (GetContentFlags() & CONTENT_OPAQUE)) {
michael@0 246 // don't need a background, we're going to paint all opaque stuff
michael@0 247 mSupportsComponentAlphaChildren = true;
michael@0 248 } else {
michael@0 249 if (HasOpaqueAncestorLayer(this) &&
michael@0 250 transform3D.Is2D(&transform) && !ThebesMatrix(transform).HasNonIntegerTranslation() &&
michael@0 251 GetParent()->GetEffectiveVisibleRegion().GetBounds().Contains(visibleRect))
michael@0 252 {
michael@0 253 // In this case we can copy up the background. See RenderLayer.
michael@0 254 mSupportsComponentAlphaChildren = true;
michael@0 255 }
michael@0 256 }
michael@0 257 } else {
michael@0 258 mSupportsComponentAlphaChildren = (GetContentFlags() & CONTENT_OPAQUE) ||
michael@0 259 (mParent && mParent->SupportsComponentAlphaChildren());
michael@0 260 }
michael@0 261
michael@0 262 ReadbackProcessor readback;
michael@0 263 readback.BuildUpdates(this);
michael@0 264
michael@0 265 Layer *layer = GetFirstChild();
michael@0 266 while (layer) {
michael@0 267 if (layer->GetType() == TYPE_THEBES) {
michael@0 268 static_cast<ThebesLayerD3D10*>(layer)->Validate(&readback);
michael@0 269 } else {
michael@0 270 static_cast<LayerD3D10*>(layer->ImplData())->Validate();
michael@0 271 }
michael@0 272 layer = layer->GetNextSibling();
michael@0 273 }
michael@0 274 }
michael@0 275
michael@0 276 } /* layers */
michael@0 277 } /* mozilla */

mercurial