1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/layers/d3d10/CanvasLayerD3D10.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,255 @@ 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 "CanvasLayerD3D10.h" 1.10 + 1.11 +#include "../d3d9/Nv3DVUtils.h" 1.12 +#include "gfxWindowsSurface.h" 1.13 +#include "gfxWindowsPlatform.h" 1.14 +#include "SurfaceStream.h" 1.15 +#include "SharedSurfaceANGLE.h" 1.16 +#include "SharedSurfaceGL.h" 1.17 +#include "gfxContext.h" 1.18 +#include "GLContext.h" 1.19 +#include "gfxPrefs.h" 1.20 + 1.21 +using namespace mozilla::gl; 1.22 +using namespace mozilla::gfx; 1.23 + 1.24 +namespace mozilla { 1.25 +namespace layers { 1.26 + 1.27 +CanvasLayerD3D10::CanvasLayerD3D10(LayerManagerD3D10 *aManager) 1.28 + : CanvasLayer(aManager, nullptr) 1.29 + , LayerD3D10(aManager) 1.30 + , mDataIsPremultiplied(false) 1.31 + , mNeedsYFlip(false) 1.32 + , mHasAlpha(true) 1.33 +{ 1.34 + mImplData = static_cast<LayerD3D10*>(this); 1.35 +} 1.36 + 1.37 +CanvasLayerD3D10::~CanvasLayerD3D10() 1.38 +{ 1.39 +} 1.40 + 1.41 +void 1.42 +CanvasLayerD3D10::Initialize(const Data& aData) 1.43 +{ 1.44 + NS_ASSERTION(mSurface == nullptr, "BasicCanvasLayer::Initialize called twice!"); 1.45 + 1.46 + if (aData.mGLContext) { 1.47 + mGLContext = aData.mGLContext; 1.48 + NS_ASSERTION(mGLContext->IsOffscreen(), "Canvas GLContext must be offscreen."); 1.49 + mDataIsPremultiplied = aData.mIsGLAlphaPremult; 1.50 + mNeedsYFlip = true; 1.51 + 1.52 + GLScreenBuffer* screen = mGLContext->Screen(); 1.53 + SurfaceStreamType streamType = 1.54 + SurfaceStream::ChooseGLStreamType(SurfaceStream::MainThread, 1.55 + screen->PreserveBuffer()); 1.56 + 1.57 + SurfaceFactory_GL* factory = nullptr; 1.58 + if (!gfxPrefs::WebGLForceLayersReadback()) { 1.59 + if (mGLContext->IsANGLE()) { 1.60 + factory = SurfaceFactory_ANGLEShareHandle::Create(mGLContext, 1.61 + device(), 1.62 + screen->Caps()); 1.63 + } 1.64 + } 1.65 + 1.66 + if (factory) { 1.67 + screen->Morph(factory, streamType); 1.68 + } 1.69 + } else if (aData.mDrawTarget) { 1.70 + mDrawTarget = aData.mDrawTarget; 1.71 + mNeedsYFlip = false; 1.72 + mDataIsPremultiplied = true; 1.73 + void *texture = mDrawTarget->GetNativeSurface(NativeSurfaceType::D3D10_TEXTURE); 1.74 + 1.75 + if (texture) { 1.76 + mTexture = static_cast<ID3D10Texture2D*>(texture); 1.77 + 1.78 + NS_ASSERTION(!aData.mGLContext, 1.79 + "CanvasLayer can't have both DrawTarget and WebGLContext/Surface"); 1.80 + 1.81 + mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height); 1.82 + device()->CreateShaderResourceView(mTexture, nullptr, getter_AddRefs(mSRView)); 1.83 + return; 1.84 + } 1.85 + 1.86 + // XXX we should store mDrawTarget and use it directly in UpdateSurface, 1.87 + // bypassing Thebes 1.88 + mSurface = mDrawTarget->Snapshot(); 1.89 + } else { 1.90 + NS_ERROR("CanvasLayer created without mSurface, mDrawTarget or mGLContext?"); 1.91 + } 1.92 + 1.93 + mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height); 1.94 + mIsD2DTexture = false; 1.95 + 1.96 + // Create a texture in case we need to readback. 1.97 + CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, mBounds.width, mBounds.height, 1, 1); 1.98 + desc.Usage = D3D10_USAGE_DYNAMIC; 1.99 + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; 1.100 + 1.101 + HRESULT hr = device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(mTexture)); 1.102 + if (FAILED(hr)) { 1.103 + NS_WARNING("Failed to create texture for CanvasLayer!"); 1.104 + return; 1.105 + } 1.106 + 1.107 + device()->CreateShaderResourceView(mTexture, nullptr, getter_AddRefs(mUploadSRView)); 1.108 +} 1.109 + 1.110 +void 1.111 +CanvasLayerD3D10::UpdateSurface() 1.112 +{ 1.113 + if (!IsDirty()) 1.114 + return; 1.115 + Painted(); 1.116 + 1.117 + if (mDrawTarget) { 1.118 + mDrawTarget->Flush(); 1.119 + } else if (mIsD2DTexture) { 1.120 + return; 1.121 + } 1.122 + 1.123 + if (!mTexture) { 1.124 + return; 1.125 + } 1.126 + 1.127 + if (mGLContext) { 1.128 + SharedSurface_GL* surf = mGLContext->RequestFrame(); 1.129 + if (!surf) { 1.130 + return; 1.131 + } 1.132 + 1.133 + switch (surf->Type()) { 1.134 + case SharedSurfaceType::EGLSurfaceANGLE: { 1.135 + SharedSurface_ANGLEShareHandle* shareSurf = SharedSurface_ANGLEShareHandle::Cast(surf); 1.136 + 1.137 + mSRView = shareSurf->GetSRV(); 1.138 + return; 1.139 + } 1.140 + case SharedSurfaceType::Basic: { 1.141 + SharedSurface_Basic* shareSurf = SharedSurface_Basic::Cast(surf); 1.142 + // WebGL reads entire surface. 1.143 + D3D10_MAPPED_TEXTURE2D map; 1.144 + 1.145 + HRESULT hr = mTexture->Map(0, D3D10_MAP_WRITE_DISCARD, 0, &map); 1.146 + 1.147 + if (FAILED(hr)) { 1.148 + NS_WARNING("Failed to map CanvasLayer texture."); 1.149 + return; 1.150 + } 1.151 + 1.152 + DataSourceSurface* frameData = shareSurf->GetData(); 1.153 + // Scope for DrawTarget, so it's destroyed before Unmap. 1.154 + { 1.155 + IntSize boundsSize(mBounds.width, mBounds.height); 1.156 + RefPtr<DrawTarget> mapDt = Factory::CreateDrawTargetForData(BackendType::CAIRO, 1.157 + (uint8_t*)map.pData, 1.158 + boundsSize, 1.159 + map.RowPitch, 1.160 + SurfaceFormat::B8G8R8A8); 1.161 + 1.162 + Rect drawRect(0, 0, frameData->GetSize().width, frameData->GetSize().height); 1.163 + mapDt->DrawSurface(frameData, drawRect, drawRect, 1.164 + DrawSurfaceOptions(), DrawOptions(1.0F, CompositionOp::OP_SOURCE)); 1.165 + mapDt->Flush(); 1.166 + } 1.167 + 1.168 + mTexture->Unmap(0); 1.169 + mSRView = mUploadSRView; 1.170 + break; 1.171 + } 1.172 + 1.173 + default: 1.174 + MOZ_CRASH("Unhandled SharedSurfaceType."); 1.175 + } 1.176 + } else if (mSurface) { 1.177 + D3D10_MAPPED_TEXTURE2D map; 1.178 + HRESULT hr = mTexture->Map(0, D3D10_MAP_WRITE_DISCARD, 0, &map); 1.179 + 1.180 + if (FAILED(hr)) { 1.181 + NS_WARNING("Failed to lock CanvasLayer texture."); 1.182 + return; 1.183 + } 1.184 + 1.185 + RefPtr<DrawTarget> destTarget = 1.186 + Factory::CreateDrawTargetForD3D10Texture(mTexture, 1.187 + SurfaceFormat::R8G8B8A8); 1.188 + Rect r(Point(0, 0), ToRect(mBounds).Size()); 1.189 + destTarget->DrawSurface(mSurface, r, r, DrawSurfaceOptions(), 1.190 + DrawOptions(1.0F, CompositionOp::OP_SOURCE)); 1.191 + 1.192 + mTexture->Unmap(0); 1.193 + mSRView = mUploadSRView; 1.194 + } 1.195 +} 1.196 + 1.197 +Layer* 1.198 +CanvasLayerD3D10::GetLayer() 1.199 +{ 1.200 + return this; 1.201 +} 1.202 + 1.203 +void 1.204 +CanvasLayerD3D10::RenderLayer() 1.205 +{ 1.206 + FirePreTransactionCallback(); 1.207 + UpdateSurface(); 1.208 + FireDidTransactionCallback(); 1.209 + 1.210 + if (!mTexture) 1.211 + return; 1.212 + 1.213 + nsIntRect visibleRect = mVisibleRegion.GetBounds(); 1.214 + 1.215 + SetEffectTransformAndOpacity(); 1.216 + 1.217 + uint8_t shaderFlags = 0; 1.218 + shaderFlags |= LoadMaskTexture(); 1.219 + shaderFlags |= mDataIsPremultiplied 1.220 + ? SHADER_PREMUL : SHADER_NON_PREMUL | SHADER_RGBA; 1.221 + shaderFlags |= mHasAlpha ? SHADER_RGBA : SHADER_RGB; 1.222 + shaderFlags |= mFilter == GraphicsFilter::FILTER_NEAREST 1.223 + ? SHADER_POINT : SHADER_LINEAR; 1.224 + ID3D10EffectTechnique* technique = SelectShader(shaderFlags); 1.225 + 1.226 + if (mSRView) { 1.227 + effect()->GetVariableByName("tRGB")->AsShaderResource()->SetResource(mSRView); 1.228 + } 1.229 + 1.230 + effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector( 1.231 + ShaderConstantRectD3D10( 1.232 + (float)mBounds.x, 1.233 + (float)mBounds.y, 1.234 + (float)mBounds.width, 1.235 + (float)mBounds.height) 1.236 + ); 1.237 + 1.238 + if (mNeedsYFlip) { 1.239 + effect()->GetVariableByName("vTextureCoords")->AsVector()->SetFloatVector( 1.240 + ShaderConstantRectD3D10( 1.241 + 0, 1.242 + 1.0f, 1.243 + 1.0f, 1.244 + -1.0f) 1.245 + ); 1.246 + } 1.247 + 1.248 + technique->GetPassByIndex(0)->Apply(0); 1.249 + device()->Draw(4, 0); 1.250 + 1.251 + if (mNeedsYFlip) { 1.252 + effect()->GetVariableByName("vTextureCoords")->AsVector()-> 1.253 + SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f)); 1.254 + } 1.255 +} 1.256 + 1.257 +} /* namespace layers */ 1.258 +} /* namespace mozilla */