gfx/layers/d3d10/ReadbackManagerD3D10.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     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 "ReadbackManagerD3D10.h"
     7 #include "ReadbackProcessor.h"
     8 #include "ReadbackLayer.h"
    10 #include "nsIThread.h"
    11 #include "nsThreadUtils.h"
    12 #include "gfxImageSurface.h"
    13 #include "gfxContext.h"
    15 namespace mozilla {
    16 namespace layers {
    18 // Structure that contains the information required to execute a readback task,
    19 // the only member accessed off the main thread here is mReadbackTexture. Since
    20 // mLayer may be released only on the main thread this object should always be
    21 // destroyed on the main thread!
    22 struct ReadbackTask {
    23   // The texture that we copied the contents of the thebeslayer to.
    24   nsRefPtr<ID3D10Texture2D> mReadbackTexture;
    25   // This exists purely to keep the ReadbackLayer alive for the lifetime of
    26   // mUpdate. Note that this addref and release should occur -solely- on the
    27   // main thread.
    28   nsRefPtr<ReadbackLayer> mLayer;
    29   ReadbackProcessor::Update mUpdate;
    30   // The origin in ThebesLayer coordinates of mReadbackTexture.
    31   gfxPoint mOrigin;
    32   // mLayer->GetBackgroundOffset() when the task is created.  We have
    33   // to save this in the ReadbackTask because it might change before
    34   // the update is delivered to the readback sink.
    35   nsIntPoint mBackgroundOffset;
    36 };
    38 // This class is created and dispatched from the Readback thread but it must be
    39 // destroyed by the main thread.
    40 class ReadbackResultWriter MOZ_FINAL : public nsIRunnable
    41 {
    42   NS_DECL_THREADSAFE_ISUPPORTS
    43 public:
    44   ReadbackResultWriter(ReadbackTask *aTask) : mTask(aTask) {}
    46   NS_IMETHODIMP Run()
    47   {
    48     ReadbackProcessor::Update *update = &mTask->mUpdate;
    50     if (!update->mLayer->GetSink()) {
    51       // This can happen when a plugin is destroyed.
    52       return NS_OK;
    53     }
    55     nsIntPoint offset = mTask->mBackgroundOffset;
    57     D3D10_TEXTURE2D_DESC desc;
    58     mTask->mReadbackTexture->GetDesc(&desc);
    60     D3D10_MAPPED_TEXTURE2D mappedTex;
    61     // We know this map will immediately succeed, as we've already mapped this
    62     // copied data on our task thread.
    63     HRESULT hr = mTask->mReadbackTexture->Map(0, D3D10_MAP_READ, 0, &mappedTex);
    65     if (FAILED(hr)) {
    66       // If this fails we're never going to get our ThebesLayer content.
    67       update->mLayer->GetSink()->SetUnknown(update->mSequenceCounter);
    68       return NS_OK;
    69     }
    71     nsRefPtr<gfxImageSurface> sourceSurface =
    72       new gfxImageSurface((unsigned char*)mappedTex.pData,
    73                           gfxIntSize(desc.Width, desc.Height),
    74                           mappedTex.RowPitch,
    75                           gfxImageFormat::RGB24);
    77     nsRefPtr<gfxContext> ctx =
    78       update->mLayer->GetSink()->BeginUpdate(update->mUpdateRect + offset,
    79                                              update->mSequenceCounter);
    81     if (ctx) {
    82       ctx->Translate(gfxPoint(offset.x, offset.y));
    83       ctx->SetSource(sourceSurface, gfxPoint(mTask->mOrigin.x,
    84                                              mTask->mOrigin.y));
    85       ctx->Paint();
    87       update->mLayer->GetSink()->EndUpdate(ctx, update->mUpdateRect + offset);
    88     }
    90     mTask->mReadbackTexture->Unmap(0);
    92     return NS_OK;
    93   }
    95 private:
    96   nsAutoPtr<ReadbackTask> mTask;
    97 };
    99 NS_IMPL_ISUPPORTS(ReadbackResultWriter, nsIRunnable)
   101 DWORD WINAPI StartTaskThread(void *aManager)
   102 {
   103   static_cast<ReadbackManagerD3D10*>(aManager)->ProcessTasks();
   105   return 0;
   106 }
   108 ReadbackManagerD3D10::ReadbackManagerD3D10()
   109   : mRefCnt(0)
   110 {
   111   ::InitializeCriticalSection(&mTaskMutex);
   112   mShutdownEvent = ::CreateEventA(nullptr, FALSE, FALSE, nullptr);
   113   mTaskSemaphore = ::CreateSemaphoreA(nullptr, 0, 1000000, nullptr);
   114   mTaskThread = ::CreateThread(nullptr, 0, StartTaskThread, this, 0, 0);
   115 }
   117 ReadbackManagerD3D10::~ReadbackManagerD3D10()
   118 {
   119   ::SetEvent(mShutdownEvent);
   121   // This shouldn't take longer than 5 seconds, if it does we're going to choose
   122   // to leak the thread and its synchronisation in favor of crashing or freezing
   123   DWORD result = ::WaitForSingleObject(mTaskThread, 5000);
   124   if (result != WAIT_TIMEOUT) {
   125     ::DeleteCriticalSection(&mTaskMutex);
   126     ::CloseHandle(mShutdownEvent);
   127     ::CloseHandle(mTaskSemaphore);
   128     ::CloseHandle(mTaskThread);
   129   } else {
   130     NS_RUNTIMEABORT("ReadbackManager: Task thread did not shutdown in 5 seconds.");
   131   }
   132 }
   134 void
   135 ReadbackManagerD3D10::PostTask(ID3D10Texture2D *aTexture, void *aUpdate, const gfxPoint &aOrigin)
   136 {
   137   ReadbackTask *task = new ReadbackTask;
   138   task->mReadbackTexture = aTexture;
   139   task->mUpdate = *static_cast<ReadbackProcessor::Update*>(aUpdate);
   140   task->mOrigin = aOrigin;
   141   task->mLayer = task->mUpdate.mLayer;
   142   task->mBackgroundOffset = task->mLayer->GetBackgroundLayerOffset();
   144   ::EnterCriticalSection(&mTaskMutex);
   145   mPendingReadbackTasks.AppendElement(task);
   146   ::LeaveCriticalSection(&mTaskMutex);
   148   ::ReleaseSemaphore(mTaskSemaphore, 1, nullptr);
   149 }
   151 HRESULT
   152 ReadbackManagerD3D10::QueryInterface(REFIID riid, void **ppvObject)
   153 {
   154   if (!ppvObject) {
   155     return E_POINTER;
   156   }
   158   if (riid == IID_IUnknown) {
   159     *ppvObject = this;
   160   } else {
   161     return E_NOINTERFACE;
   162   }
   164   return S_OK;
   165 }
   167 ULONG
   168 ReadbackManagerD3D10::AddRef()
   169 {
   170   NS_ASSERTION(NS_IsMainThread(),
   171     "ReadbackManagerD3D10 should only be refcounted on main thread.");
   172   return ++mRefCnt;
   173 }
   175 ULONG
   176 ReadbackManagerD3D10::Release()
   177 {
   178   NS_ASSERTION(NS_IsMainThread(),
   179     "ReadbackManagerD3D10 should only be refcounted on main thread.");
   180   ULONG newRefCnt = --mRefCnt;
   181   if (!newRefCnt) {
   182     mRefCnt++;
   183     delete this;
   184   }
   185   return newRefCnt;
   186 }
   188 void
   189 ReadbackManagerD3D10::ProcessTasks()
   190 {
   191   HANDLE handles[] = { mTaskSemaphore, mShutdownEvent };
   193   while (true) {
   194     DWORD result = ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
   195     if (result != WAIT_OBJECT_0) {
   196       return;
   197     }
   199     ::EnterCriticalSection(&mTaskMutex);
   200     if (mPendingReadbackTasks.Length() == 0) {
   201       NS_RUNTIMEABORT("Trying to read from an empty array, bad bad bad");
   202     }
   203     ReadbackTask *nextReadbackTask = mPendingReadbackTasks[0].forget();
   204     mPendingReadbackTasks.RemoveElementAt(0);
   205     ::LeaveCriticalSection(&mTaskMutex);
   207     // We want to block here until the texture contents are available, the
   208     // easiest thing is to simply map and unmap.
   209     D3D10_MAPPED_TEXTURE2D mappedTex;
   210     nextReadbackTask->mReadbackTexture->Map(0, D3D10_MAP_READ, 0, &mappedTex);
   211     nextReadbackTask->mReadbackTexture->Unmap(0);
   213     // We can only send the update to the sink on the main thread, so post an
   214     // event there to do so. Ownership of the task is passed from
   215     // mPendingReadbackTasks to ReadbackResultWriter here.
   216     nsCOMPtr<nsIThread> thread = do_GetMainThread();
   217     thread->Dispatch(new ReadbackResultWriter(nextReadbackTask),
   218                      nsIEventTarget::DISPATCH_NORMAL);
   219   }
   220 }
   222 }
   223 }

mercurial