gfx/layers/ipc/ShadowLayerUtilsGralloc.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: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     2  * vim: sw=2 ts=8 et :
     3  */
     4 /* This Source Code Form is subject to the terms of the Mozilla Public
     5  * License, v. 2.0. If a copy of the MPL was not distributed with this
     6  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     8 #include "mozilla/DebugOnly.h"
    10 #include "mozilla/gfx/Point.h"
    11 #include "mozilla/layers/PGrallocBufferChild.h"
    12 #include "mozilla/layers/PGrallocBufferParent.h"
    13 #include "mozilla/layers/LayerTransactionChild.h"
    14 #include "mozilla/layers/ShadowLayers.h"
    15 #include "mozilla/layers/LayerManagerComposite.h"
    16 #include "mozilla/layers/CompositorTypes.h"
    17 #include "mozilla/layers/TextureHost.h"
    18 #include "mozilla/unused.h"
    19 #include "nsXULAppAPI.h"
    21 #include "ShadowLayerUtilsGralloc.h"
    23 #include "nsIMemoryReporter.h"
    25 #include "gfxPlatform.h"
    26 #include "gfx2DGlue.h"
    27 #include "GLContext.h"
    29 #include "GeckoProfiler.h"
    31 #include "cutils/properties.h"
    33 #include "MainThreadUtils.h"
    35 using namespace android;
    36 using namespace base;
    37 using namespace mozilla::layers;
    38 using namespace mozilla::gl;
    40 namespace IPC {
    42 void
    43 ParamTraits<MagicGrallocBufferHandle>::Write(Message* aMsg,
    44                                              const paramType& aParam)
    45 {
    46 #if ANDROID_VERSION >= 19
    47   sp<GraphicBuffer> flattenable = aParam.mGraphicBuffer;
    48 #else
    49   Flattenable *flattenable = aParam.mGraphicBuffer.get();
    50 #endif
    51   size_t nbytes = flattenable->getFlattenedSize();
    52   size_t nfds = flattenable->getFdCount();
    54   char data[nbytes];
    55   int fds[nfds];
    57 #if ANDROID_VERSION >= 19
    58   // Make a copy of "data" and "fds" for flatten() to avoid casting problem
    59   void *pdata = (void *)data;
    60   int *pfds = fds;
    62   flattenable->flatten(pdata, nbytes, pfds, nfds);
    64   // In Kitkat, flatten() will change the value of nbytes and nfds, which dues
    65   // to multiple parcelable object consumption. The actual size and fd count
    66   // which returned by getFlattenedSize() and getFdCount() are not changed.
    67   // So we change nbytes and nfds back by call corresponding calls.
    68   nbytes = flattenable->getFlattenedSize();
    69   nfds = flattenable->getFdCount();
    70 #else
    71   flattenable->flatten(data, nbytes, fds, nfds);
    72 #endif
    74   aMsg->WriteSize(nbytes);
    75   aMsg->WriteSize(nfds);
    77   aMsg->WriteBytes(data, nbytes);
    78   for (size_t n = 0; n < nfds; ++n) {
    79     // These buffers can't die in transit because they're created
    80     // synchonously and the parent-side buffer can only be dropped if
    81     // there's a crash.
    82     aMsg->WriteFileDescriptor(FileDescriptor(fds[n], false));
    83   }
    84 }
    86 bool
    87 ParamTraits<MagicGrallocBufferHandle>::Read(const Message* aMsg,
    88                                             void** aIter, paramType* aResult)
    89 {
    90   size_t nbytes;
    91   size_t nfds;
    92   const char* data;
    94   if (!aMsg->ReadSize(aIter, &nbytes) ||
    95       !aMsg->ReadSize(aIter, &nfds) ||
    96       !aMsg->ReadBytes(aIter, &data, nbytes)) {
    97     return false;
    98   }
   100   int fds[nfds];
   102   for (size_t n = 0; n < nfds; ++n) {
   103     FileDescriptor fd;
   104     if (!aMsg->ReadFileDescriptor(aIter, &fd)) {
   105       return false;
   106     }
   107     // If the GraphicBuffer was shared cross-process, SCM_RIGHTS does
   108     // the right thing and dup's the fd.  If it's shared cross-thread,
   109     // SCM_RIGHTS doesn't dup the fd.  That's surprising, but we just
   110     // deal with it here.  NB: only the "default" (master) process can
   111     // alloc gralloc buffers.
   112     bool sameProcess = (XRE_GetProcessType() == GeckoProcessType_Default);
   113     int dupFd = sameProcess ? dup(fd.fd) : fd.fd;
   114     fds[n] = dupFd;
   115   }
   117   sp<GraphicBuffer> buffer(new GraphicBuffer());
   118 #if ANDROID_VERSION >= 19
   119   // Make a copy of "data" and "fds" for unflatten() to avoid casting problem
   120   void const *pdata = (void const *)data;
   121   int const *pfds = fds;
   123   if (NO_ERROR == buffer->unflatten(pdata, nbytes, pfds, nfds)) {
   124 #else
   125   Flattenable *flattenable = buffer.get();
   127   if (NO_ERROR == flattenable->unflatten(data, nbytes, fds, nfds)) {
   128 #endif
   129     aResult->mGraphicBuffer = buffer;
   130     return true;
   131   }
   132   return false;
   133 }
   135 } // namespace IPC
   137 namespace mozilla {
   138 namespace layers {
   140 MagicGrallocBufferHandle::MagicGrallocBufferHandle(const sp<GraphicBuffer>& aGraphicBuffer)
   141   : mGraphicBuffer(aGraphicBuffer)
   142 {
   143 }
   145 //-----------------------------------------------------------------------------
   146 // Parent process
   148 static gfxImageFormat
   149 ImageFormatForPixelFormat(android::PixelFormat aFormat)
   150 {
   151   switch (aFormat) {
   152   case PIXEL_FORMAT_RGBA_8888:
   153     return gfxImageFormat::ARGB32;
   154   case PIXEL_FORMAT_RGBX_8888:
   155     return gfxImageFormat::RGB24;
   156   case PIXEL_FORMAT_RGB_565:
   157     return gfxImageFormat::RGB16_565;
   158   default:
   159     MOZ_CRASH("Unknown gralloc pixel format");
   160   }
   161   return gfxImageFormat::ARGB32;
   162 }
   164 static android::PixelFormat
   165 PixelFormatForImageFormat(gfxImageFormat aFormat)
   166 {
   167   switch (aFormat) {
   168   case gfxImageFormat::ARGB32:
   169     return android::PIXEL_FORMAT_RGBA_8888;
   170   case gfxImageFormat::RGB24:
   171     return android::PIXEL_FORMAT_RGBX_8888;
   172   case gfxImageFormat::RGB16_565:
   173     return android::PIXEL_FORMAT_RGB_565;
   174   case gfxImageFormat::A8:
   175     NS_WARNING("gralloc does not support gfxImageFormat::A8");
   176     return android::PIXEL_FORMAT_UNKNOWN;
   177   default:
   178     MOZ_CRASH("Unknown gralloc pixel format");
   179   }
   180   return android::PIXEL_FORMAT_RGBA_8888;
   181 }
   183 static size_t
   184 BytesPerPixelForPixelFormat(android::PixelFormat aFormat)
   185 {
   186   switch (aFormat) {
   187   case PIXEL_FORMAT_RGBA_8888:
   188   case PIXEL_FORMAT_RGBX_8888:
   189   case PIXEL_FORMAT_BGRA_8888:
   190     return 4;
   191   case PIXEL_FORMAT_RGB_888:
   192     return 3;
   193   case PIXEL_FORMAT_RGB_565:
   194   case PIXEL_FORMAT_RGBA_5551:
   195   case PIXEL_FORMAT_RGBA_4444:
   196     return 2;
   197   default:
   198     return 0;
   199   }
   200   return 0;
   201 }
   203 static android::PixelFormat
   204 PixelFormatForContentType(gfxContentType aContentType)
   205 {
   206   return PixelFormatForImageFormat(
   207     gfxPlatform::GetPlatform()->OptimalFormatForContent(aContentType));
   208 }
   210 static gfxContentType
   211 ContentTypeFromPixelFormat(android::PixelFormat aFormat)
   212 {
   213   return gfxASurface::ContentFromFormat(ImageFormatForPixelFormat(aFormat));
   214 }
   216 class GrallocReporter MOZ_FINAL : public nsIMemoryReporter
   217 {
   218   friend class GrallocBufferActor;
   220 public:
   221   NS_DECL_ISUPPORTS
   223   GrallocReporter()
   224   {
   225 #ifdef DEBUG
   226     // There must be only one instance of this class, due to |sAmount|
   227     // being static.  Assert this.
   228     static bool hasRun = false;
   229     MOZ_ASSERT(!hasRun);
   230     hasRun = true;
   231 #endif
   232   }
   234   NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
   235                             nsISupports* aData)
   236   {
   237     return MOZ_COLLECT_REPORT(
   238       "gralloc", KIND_OTHER, UNITS_BYTES, sAmount,
   239 "Special RAM that can be shared between processes and directly accessed by "
   240 "both the CPU and GPU. Gralloc memory is usually a relatively precious "
   241 "resource, with much less available than generic RAM. When it's exhausted, "
   242 "graphics performance can suffer. This value can be incorrect because of race "
   243 "conditions.");
   244   }
   246 private:
   247   static int64_t sAmount;
   248 };
   250 NS_IMPL_ISUPPORTS(GrallocReporter, nsIMemoryReporter)
   252 int64_t GrallocReporter::sAmount = 0;
   254 void InitGralloc() {
   255   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   256   RegisterStrongMemoryReporter(new GrallocReporter());
   257 }
   259 GrallocBufferActor::GrallocBufferActor()
   260 : mAllocBytes(0)
   261 , mTextureHost(nullptr)
   262 {
   263 }
   265 GrallocBufferActor::~GrallocBufferActor()
   266 {
   267   if (mAllocBytes > 0) {
   268     GrallocReporter::sAmount -= mAllocBytes;
   269   }
   270 }
   272 /*static*/ PGrallocBufferParent*
   273 GrallocBufferActor::Create(const gfx::IntSize& aSize,
   274                            const uint32_t& aFormat,
   275                            const uint32_t& aUsage,
   276                            MaybeMagicGrallocBufferHandle* aOutHandle)
   277 {
   278   PROFILER_LABEL("GrallocBufferActor", "Create");
   279   GrallocBufferActor* actor = new GrallocBufferActor();
   280   *aOutHandle = null_t();
   281   uint32_t format = aFormat;
   282   uint32_t usage = aUsage;
   284   if (format == 0 || usage == 0) {
   285     printf_stderr("GrallocBufferActor::Create -- format and usage must be non-zero");
   286     return actor;
   287   }
   289   // If the requested size is too big (i.e. exceeds the commonly used max GL texture size)
   290   // then we risk OOMing the parent process. It's better to just deny the allocation and
   291   // kill the child process, which is what the following code does.
   292   // TODO: actually use GL_MAX_TEXTURE_SIZE instead of hardcoding 4096
   293   if (aSize.width > 4096 || aSize.height > 4096) {
   294     printf_stderr("GrallocBufferActor::Create -- requested gralloc buffer is too big. Killing child instead.");
   295     delete actor;
   296     return nullptr;
   297   }
   299   sp<GraphicBuffer> buffer(new GraphicBuffer(aSize.width, aSize.height, format, usage));
   300   if (buffer->initCheck() != OK)
   301     return actor;
   303   size_t bpp = BytesPerPixelForPixelFormat(format);
   304   actor->mAllocBytes = aSize.width * aSize.height * bpp;
   305   GrallocReporter::sAmount += actor->mAllocBytes;
   307   actor->mGraphicBuffer = buffer;
   308   *aOutHandle = MagicGrallocBufferHandle(buffer);
   310   return actor;
   311 }
   313 void GrallocBufferActor::ActorDestroy(ActorDestroyReason)
   314 {
   315   // Used only for hacky fix for bug 966446.
   316   if (mTextureHost) {
   317     mTextureHost->ForgetBufferActor();
   318     mTextureHost = nullptr;
   319   }
   320 }
   322 void GrallocBufferActor::AddTextureHost(TextureHost* aTextureHost)
   323 {
   324   mTextureHost = aTextureHost;
   325 }
   327 void GrallocBufferActor::RemoveTextureHost()
   328 {
   329   mTextureHost = nullptr;
   330 }
   332 /*static*/ bool
   333 LayerManagerComposite::SupportsDirectTexturing()
   334 {
   335   return true;
   336 }
   338 /*static*/ void
   339 LayerManagerComposite::PlatformSyncBeforeReplyUpdate()
   340 {
   341   // Nothing to be done for gralloc.
   342 }
   344 //-----------------------------------------------------------------------------
   345 // Child process
   347 /*static*/ PGrallocBufferChild*
   348 GrallocBufferActor::Create()
   349 {
   350   return new GrallocBufferActor();
   351 }
   353 void
   354 GrallocBufferActor::InitFromHandle(const MagicGrallocBufferHandle& aHandle)
   355 {
   356   MOZ_ASSERT(!mGraphicBuffer.get());
   357   MOZ_ASSERT(aHandle.mGraphicBuffer.get());
   359   mGraphicBuffer = aHandle.mGraphicBuffer;
   360 }
   362 PGrallocBufferChild*
   363 ShadowLayerForwarder::AllocGrallocBuffer(const gfx::IntSize& aSize,
   364                                          uint32_t aFormat,
   365                                          uint32_t aUsage,
   366                                          MaybeMagicGrallocBufferHandle* aHandle)
   367 {
   368   if (!mShadowManager->IPCOpen()) {
   369     return nullptr;
   370   }
   371   return mShadowManager->SendPGrallocBufferConstructor(aSize, aFormat, aUsage, aHandle);
   372 }
   374 void
   375 ShadowLayerForwarder::DeallocGrallocBuffer(PGrallocBufferChild* aChild)
   376 {
   377   MOZ_ASSERT(aChild);
   378   PGrallocBufferChild::Send__delete__(aChild);
   379 }
   381 //-----------------------------------------------------------------------------
   382 // Both processes
   384 android::GraphicBuffer*
   385 GrallocBufferActor::GetGraphicBuffer()
   386 {
   387   return mGraphicBuffer.get();
   388 }
   390 /*static*/ void
   391 ShadowLayerForwarder::PlatformSyncBeforeUpdate()
   392 {
   393   // Nothing to be done for gralloc.
   394 }
   396 } // namespace layers
   397 } // namespace mozilla

mercurial