gfx/layers/d3d10/CanvasLayerD3D10.cpp

changeset 0
6474c204b198
     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 */

mercurial