gfx/layers/d3d9/CanvasLayerD3D9.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/layers/d3d9/CanvasLayerD3D9.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,212 @@
     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 +
    1.10 +#include "mozilla/layers/PLayerTransaction.h"
    1.11 +
    1.12 +#include "gfxWindowsSurface.h"
    1.13 +#include "gfxWindowsPlatform.h"
    1.14 +#include "SurfaceStream.h"
    1.15 +#include "SharedSurfaceGL.h"
    1.16 +#include "GLContext.h"
    1.17 +#include "CanvasLayerD3D9.h"
    1.18 +
    1.19 +using namespace mozilla::gfx;
    1.20 +using namespace mozilla::gl;
    1.21 +
    1.22 +namespace mozilla {
    1.23 +namespace layers {
    1.24 +
    1.25 +CanvasLayerD3D9::CanvasLayerD3D9(LayerManagerD3D9 *aManager)
    1.26 +  : CanvasLayer(aManager, nullptr)
    1.27 +  , LayerD3D9(aManager)
    1.28 +  , mDataIsPremultiplied(false)
    1.29 +  , mNeedsYFlip(false)
    1.30 +  , mHasAlpha(true)
    1.31 +{
    1.32 +    mImplData = static_cast<LayerD3D9*>(this);
    1.33 +    aManager->deviceManager()->mLayersWithResources.AppendElement(this);
    1.34 +}
    1.35 +
    1.36 +CanvasLayerD3D9::~CanvasLayerD3D9()
    1.37 +{
    1.38 +  if (mD3DManager) {
    1.39 +    mD3DManager->deviceManager()->mLayersWithResources.RemoveElement(this);
    1.40 +  }
    1.41 +}
    1.42 +
    1.43 +void
    1.44 +CanvasLayerD3D9::Initialize(const Data& aData)
    1.45 +{
    1.46 +  NS_ASSERTION(mDrawTarget == nullptr, "BasicCanvasLayer::Initialize called twice!");
    1.47 +
    1.48 +  if (aData.mDrawTarget) {
    1.49 +    mDrawTarget = aData.mDrawTarget;
    1.50 +    mNeedsYFlip = false;
    1.51 +    mDataIsPremultiplied = true;
    1.52 +  } else if (aData.mGLContext) {
    1.53 +    mGLContext = aData.mGLContext;
    1.54 +    NS_ASSERTION(mGLContext->IsOffscreen(), "Canvas GLContext must be offscreen.");
    1.55 +    mDataIsPremultiplied = aData.mIsGLAlphaPremult;
    1.56 +    mNeedsYFlip = true;
    1.57 +  } else {
    1.58 +    NS_ERROR("CanvasLayer created without mGLContext or mDrawTarget?");
    1.59 +  }
    1.60 +
    1.61 +  mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
    1.62 +
    1.63 +  CreateTexture();
    1.64 +}
    1.65 +
    1.66 +void
    1.67 +CanvasLayerD3D9::UpdateSurface()
    1.68 +{
    1.69 +  if (!IsDirty() && mTexture)
    1.70 +    return;
    1.71 +  Painted();
    1.72 +
    1.73 +  if (!mTexture) {
    1.74 +    CreateTexture();
    1.75 +
    1.76 +    if (!mTexture) {
    1.77 +      NS_WARNING("CanvasLayerD3D9::Updated called but no texture present and creation failed!");
    1.78 +      return;
    1.79 +    }
    1.80 +  }
    1.81 +
    1.82 +  RefPtr<SourceSurface> surface;
    1.83 +
    1.84 +  if (mGLContext) {
    1.85 +    SharedSurface_GL* surf = mGLContext->RequestFrame();
    1.86 +    if (!surf)
    1.87 +        return;
    1.88 +
    1.89 +    SharedSurface_Basic* shareSurf = SharedSurface_Basic::Cast(surf);
    1.90 +    surface = shareSurf->GetData();
    1.91 +  } else {
    1.92 +    surface = mDrawTarget->Snapshot();
    1.93 +  }
    1.94 +
    1.95 +  // WebGL reads entire surface.
    1.96 +  LockTextureRectD3D9 textureLock(mTexture);
    1.97 +  if (!textureLock.HasLock()) {
    1.98 +    NS_WARNING("Failed to lock CanvasLayer texture.");
    1.99 +    return;
   1.100 +  }
   1.101 +
   1.102 +  D3DLOCKED_RECT rect = textureLock.GetLockRect();
   1.103 +  IntSize boundsSize(mBounds.width, mBounds.height);
   1.104 +  RefPtr<DrawTarget> rectDt = Factory::CreateDrawTargetForData(BackendType::CAIRO,
   1.105 +                                                               (uint8_t*)rect.pBits,
   1.106 +                                                               boundsSize,
   1.107 +                                                               rect.Pitch,
   1.108 +                                                               SurfaceFormat::B8G8R8A8);
   1.109 +
   1.110 +  Rect drawRect(0, 0, surface->GetSize().width, surface->GetSize().height);
   1.111 +  rectDt->DrawSurface(surface, drawRect, drawRect,
   1.112 +                      DrawSurfaceOptions(),  DrawOptions(1.0F, CompositionOp::OP_SOURCE));
   1.113 +  rectDt->Flush();
   1.114 +}
   1.115 +
   1.116 +Layer*
   1.117 +CanvasLayerD3D9::GetLayer()
   1.118 +{
   1.119 +  return this;
   1.120 +}
   1.121 +
   1.122 +void
   1.123 +CanvasLayerD3D9::RenderLayer()
   1.124 +{
   1.125 +  FirePreTransactionCallback();
   1.126 +  UpdateSurface();
   1.127 +  if (mD3DManager->CompositingDisabled()) {
   1.128 +    return;
   1.129 +  }
   1.130 +  FireDidTransactionCallback();
   1.131 +
   1.132 +  if (!mTexture)
   1.133 +    return;
   1.134 +
   1.135 +  /*
   1.136 +   * We flip the Y axis here, note we can only do this because we are in
   1.137 +   * CULL_NONE mode!
   1.138 +   */
   1.139 +
   1.140 +  ShaderConstantRect quad(0, 0, mBounds.width, mBounds.height);
   1.141 +  if (mNeedsYFlip) {
   1.142 +    quad.mHeight = (float)-mBounds.height;
   1.143 +    quad.mY = (float)mBounds.height;
   1.144 +  }
   1.145 +
   1.146 +  device()->SetVertexShaderConstantF(CBvLayerQuad, quad, 1);
   1.147 +
   1.148 +  SetShaderTransformAndOpacity();
   1.149 +
   1.150 +  if (mHasAlpha) {
   1.151 +    mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER, GetMaskLayer());
   1.152 +  } else {
   1.153 +    mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBLAYER, GetMaskLayer());
   1.154 +  }
   1.155 +
   1.156 +  if (mFilter == GraphicsFilter::FILTER_NEAREST) {
   1.157 +    device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
   1.158 +    device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
   1.159 +  }
   1.160 +  if (!mDataIsPremultiplied) {
   1.161 +    device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
   1.162 +    device()->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
   1.163 +  }
   1.164 +  device()->SetTexture(0, mTexture);
   1.165 +  device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
   1.166 +  if (!mDataIsPremultiplied) {
   1.167 +    device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
   1.168 +    device()->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
   1.169 +  }
   1.170 +  if (mFilter == GraphicsFilter::FILTER_NEAREST) {
   1.171 +    device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
   1.172 +    device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
   1.173 +  }
   1.174 +}
   1.175 +
   1.176 +void
   1.177 +CanvasLayerD3D9::CleanResources()
   1.178 +{
   1.179 +  if (mD3DManager->deviceManager()->HasDynamicTextures()) {
   1.180 +    // In this case we have a texture in POOL_DEFAULT
   1.181 +    mTexture = nullptr;
   1.182 +  }
   1.183 +}
   1.184 +
   1.185 +void
   1.186 +CanvasLayerD3D9::LayerManagerDestroyed()
   1.187 +{
   1.188 +  mD3DManager->deviceManager()->mLayersWithResources.RemoveElement(this);
   1.189 +  mD3DManager = nullptr;
   1.190 +}
   1.191 +
   1.192 +void
   1.193 +CanvasLayerD3D9::CreateTexture()
   1.194 +{
   1.195 +  HRESULT hr;
   1.196 +  if (mD3DManager->deviceManager()->HasDynamicTextures()) {
   1.197 +    hr = device()->CreateTexture(mBounds.width, mBounds.height, 1, D3DUSAGE_DYNAMIC,
   1.198 +                                 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT,
   1.199 +                                 getter_AddRefs(mTexture), nullptr);
   1.200 +  } else {
   1.201 +    // D3DPOOL_MANAGED is fine here since we require Dynamic Textures for D3D9Ex
   1.202 +    // devices.
   1.203 +    hr = device()->CreateTexture(mBounds.width, mBounds.height, 1, 0,
   1.204 +                                 D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
   1.205 +                                 getter_AddRefs(mTexture), nullptr);
   1.206 +  }
   1.207 +  if (FAILED(hr)) {
   1.208 +    mD3DManager->ReportFailure(NS_LITERAL_CSTRING("CanvasLayerD3D9::CreateTexture() failed"),
   1.209 +                                 hr);
   1.210 +    return;
   1.211 +  }
   1.212 +}
   1.213 +
   1.214 +} /* namespace layers */
   1.215 +} /* namespace mozilla */

mercurial