gfx/layers/d3d10/CanvasLayerD3D10.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.

     1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     2  * This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "CanvasLayerD3D10.h"
     8 #include "../d3d9/Nv3DVUtils.h"
     9 #include "gfxWindowsSurface.h"
    10 #include "gfxWindowsPlatform.h"
    11 #include "SurfaceStream.h"
    12 #include "SharedSurfaceANGLE.h"
    13 #include "SharedSurfaceGL.h"
    14 #include "gfxContext.h"
    15 #include "GLContext.h"
    16 #include "gfxPrefs.h"
    18 using namespace mozilla::gl;
    19 using namespace mozilla::gfx;
    21 namespace mozilla {
    22 namespace layers {
    24 CanvasLayerD3D10::CanvasLayerD3D10(LayerManagerD3D10 *aManager)
    25   : CanvasLayer(aManager, nullptr)
    26   , LayerD3D10(aManager)
    27   , mDataIsPremultiplied(false)
    28   , mNeedsYFlip(false)
    29   , mHasAlpha(true)
    30 {
    31     mImplData = static_cast<LayerD3D10*>(this);
    32 }
    34 CanvasLayerD3D10::~CanvasLayerD3D10()
    35 {
    36 }
    38 void
    39 CanvasLayerD3D10::Initialize(const Data& aData)
    40 {
    41   NS_ASSERTION(mSurface == nullptr, "BasicCanvasLayer::Initialize called twice!");
    43   if (aData.mGLContext) {
    44     mGLContext = aData.mGLContext;
    45     NS_ASSERTION(mGLContext->IsOffscreen(), "Canvas GLContext must be offscreen.");
    46     mDataIsPremultiplied = aData.mIsGLAlphaPremult;
    47     mNeedsYFlip = true;
    49     GLScreenBuffer* screen = mGLContext->Screen();
    50     SurfaceStreamType streamType =
    51         SurfaceStream::ChooseGLStreamType(SurfaceStream::MainThread,
    52                                           screen->PreserveBuffer());
    54     SurfaceFactory_GL* factory = nullptr;
    55     if (!gfxPrefs::WebGLForceLayersReadback()) {
    56       if (mGLContext->IsANGLE()) {
    57         factory = SurfaceFactory_ANGLEShareHandle::Create(mGLContext,
    58                                                           device(),
    59                                                           screen->Caps());
    60       }
    61     }
    63     if (factory) {
    64       screen->Morph(factory, streamType);
    65     }
    66   } else if (aData.mDrawTarget) {
    67     mDrawTarget = aData.mDrawTarget;
    68     mNeedsYFlip = false;
    69     mDataIsPremultiplied = true;
    70     void *texture = mDrawTarget->GetNativeSurface(NativeSurfaceType::D3D10_TEXTURE);
    72     if (texture) {
    73       mTexture = static_cast<ID3D10Texture2D*>(texture);
    75       NS_ASSERTION(!aData.mGLContext,
    76                    "CanvasLayer can't have both DrawTarget and WebGLContext/Surface");
    78       mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
    79       device()->CreateShaderResourceView(mTexture, nullptr, getter_AddRefs(mSRView));
    80       return;
    81     }
    83     // XXX we should store mDrawTarget and use it directly in UpdateSurface,
    84     // bypassing Thebes
    85     mSurface = mDrawTarget->Snapshot();
    86   } else {
    87     NS_ERROR("CanvasLayer created without mSurface, mDrawTarget or mGLContext?");
    88   }
    90   mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
    91   mIsD2DTexture = false;
    93   // Create a texture in case we need to readback.
    94   CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, mBounds.width, mBounds.height, 1, 1);
    95   desc.Usage = D3D10_USAGE_DYNAMIC;
    96   desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
    98   HRESULT hr = device()->CreateTexture2D(&desc, nullptr, getter_AddRefs(mTexture));
    99   if (FAILED(hr)) {
   100     NS_WARNING("Failed to create texture for CanvasLayer!");
   101     return;
   102   }
   104   device()->CreateShaderResourceView(mTexture, nullptr, getter_AddRefs(mUploadSRView));
   105 }
   107 void
   108 CanvasLayerD3D10::UpdateSurface()
   109 {
   110   if (!IsDirty())
   111     return;
   112   Painted();
   114   if (mDrawTarget) {
   115     mDrawTarget->Flush();
   116   } else if (mIsD2DTexture) {
   117     return;
   118   }
   120   if (!mTexture) {
   121     return;
   122   }
   124   if (mGLContext) {
   125     SharedSurface_GL* surf = mGLContext->RequestFrame();
   126     if (!surf) {
   127       return;
   128     }
   130     switch (surf->Type()) {
   131       case SharedSurfaceType::EGLSurfaceANGLE: {
   132         SharedSurface_ANGLEShareHandle* shareSurf = SharedSurface_ANGLEShareHandle::Cast(surf);
   134         mSRView = shareSurf->GetSRV();
   135         return;
   136       }
   137       case SharedSurfaceType::Basic: {
   138         SharedSurface_Basic* shareSurf = SharedSurface_Basic::Cast(surf);
   139         // WebGL reads entire surface.
   140         D3D10_MAPPED_TEXTURE2D map;
   142         HRESULT hr = mTexture->Map(0, D3D10_MAP_WRITE_DISCARD, 0, &map);
   144         if (FAILED(hr)) {
   145           NS_WARNING("Failed to map CanvasLayer texture.");
   146           return;
   147         }
   149         DataSourceSurface* frameData = shareSurf->GetData();
   150         // Scope for DrawTarget, so it's destroyed before Unmap.
   151         {
   152           IntSize boundsSize(mBounds.width, mBounds.height);
   153           RefPtr<DrawTarget> mapDt = Factory::CreateDrawTargetForData(BackendType::CAIRO,
   154                                                                       (uint8_t*)map.pData,
   155                                                                       boundsSize,
   156                                                                       map.RowPitch,
   157                                                                       SurfaceFormat::B8G8R8A8);
   159           Rect drawRect(0, 0, frameData->GetSize().width, frameData->GetSize().height);
   160           mapDt->DrawSurface(frameData, drawRect, drawRect,
   161                              DrawSurfaceOptions(),  DrawOptions(1.0F, CompositionOp::OP_SOURCE));
   162           mapDt->Flush();
   163         }
   165         mTexture->Unmap(0);
   166         mSRView = mUploadSRView;
   167         break;
   168       }
   170       default:
   171         MOZ_CRASH("Unhandled SharedSurfaceType.");
   172     }
   173   } else if (mSurface) {
   174     D3D10_MAPPED_TEXTURE2D map;
   175     HRESULT hr = mTexture->Map(0, D3D10_MAP_WRITE_DISCARD, 0, &map);
   177     if (FAILED(hr)) {
   178       NS_WARNING("Failed to lock CanvasLayer texture.");
   179       return;
   180     }
   182     RefPtr<DrawTarget> destTarget =
   183       Factory::CreateDrawTargetForD3D10Texture(mTexture,
   184                                                SurfaceFormat::R8G8B8A8);
   185     Rect r(Point(0, 0), ToRect(mBounds).Size());
   186     destTarget->DrawSurface(mSurface, r, r, DrawSurfaceOptions(),
   187                             DrawOptions(1.0F, CompositionOp::OP_SOURCE));
   189     mTexture->Unmap(0);
   190     mSRView = mUploadSRView;
   191   }
   192 }
   194 Layer*
   195 CanvasLayerD3D10::GetLayer()
   196 {
   197   return this;
   198 }
   200 void
   201 CanvasLayerD3D10::RenderLayer()
   202 {
   203   FirePreTransactionCallback();
   204   UpdateSurface();
   205   FireDidTransactionCallback();
   207   if (!mTexture)
   208     return;
   210   nsIntRect visibleRect = mVisibleRegion.GetBounds();
   212   SetEffectTransformAndOpacity();
   214   uint8_t shaderFlags = 0;
   215   shaderFlags |= LoadMaskTexture();
   216   shaderFlags |= mDataIsPremultiplied
   217                 ? SHADER_PREMUL : SHADER_NON_PREMUL | SHADER_RGBA;
   218   shaderFlags |= mHasAlpha ? SHADER_RGBA : SHADER_RGB;
   219   shaderFlags |= mFilter == GraphicsFilter::FILTER_NEAREST
   220                 ? SHADER_POINT : SHADER_LINEAR;
   221   ID3D10EffectTechnique* technique = SelectShader(shaderFlags);
   223   if (mSRView) {
   224     effect()->GetVariableByName("tRGB")->AsShaderResource()->SetResource(mSRView);
   225   }
   227   effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
   228     ShaderConstantRectD3D10(
   229       (float)mBounds.x,
   230       (float)mBounds.y,
   231       (float)mBounds.width,
   232       (float)mBounds.height)
   233     );
   235   if (mNeedsYFlip) {
   236     effect()->GetVariableByName("vTextureCoords")->AsVector()->SetFloatVector(
   237       ShaderConstantRectD3D10(
   238         0,
   239         1.0f,
   240         1.0f,
   241         -1.0f)
   242       );
   243   }
   245   technique->GetPassByIndex(0)->Apply(0);
   246   device()->Draw(4, 0);
   248   if (mNeedsYFlip) {
   249     effect()->GetVariableByName("vTextureCoords")->AsVector()->
   250       SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
   251   }
   252 }
   254 } /* namespace layers */
   255 } /* namespace mozilla */

mercurial