gfx/layers/opengl/GrallocTextureHost.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.

michael@0 1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
michael@0 2 // * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "GLContext.h"
michael@0 7 #include "gfx2DGlue.h"
michael@0 8 #include <ui/GraphicBuffer.h>
michael@0 9 #include "GrallocImages.h" // for GrallocImage
michael@0 10 #include "mozilla/layers/GrallocTextureHost.h"
michael@0 11 #include "mozilla/layers/CompositorOGL.h"
michael@0 12 #include "EGLImageHelpers.h"
michael@0 13 #include "GLReadTexImageHelper.h"
michael@0 14
michael@0 15 namespace mozilla {
michael@0 16 namespace layers {
michael@0 17
michael@0 18 using namespace android;
michael@0 19
michael@0 20 static gfx::SurfaceFormat
michael@0 21 SurfaceFormatForAndroidPixelFormat(android::PixelFormat aFormat,
michael@0 22 bool swapRB = false)
michael@0 23 {
michael@0 24 switch (aFormat) {
michael@0 25 case android::PIXEL_FORMAT_BGRA_8888:
michael@0 26 return swapRB ? gfx::SurfaceFormat::R8G8B8A8 : gfx::SurfaceFormat::B8G8R8A8;
michael@0 27 case android::PIXEL_FORMAT_RGBA_8888:
michael@0 28 return swapRB ? gfx::SurfaceFormat::B8G8R8A8 : gfx::SurfaceFormat::R8G8B8A8;
michael@0 29 case android::PIXEL_FORMAT_RGBX_8888:
michael@0 30 return swapRB ? gfx::SurfaceFormat::B8G8R8X8 : gfx::SurfaceFormat::R8G8B8X8;
michael@0 31 case android::PIXEL_FORMAT_RGB_565:
michael@0 32 return gfx::SurfaceFormat::R5G6B5;
michael@0 33 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
michael@0 34 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
michael@0 35 case HAL_PIXEL_FORMAT_YCbCr_422_I:
michael@0 36 case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
michael@0 37 case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
michael@0 38 case HAL_PIXEL_FORMAT_YV12:
michael@0 39 return gfx::SurfaceFormat::R8G8B8A8; // yup, use SurfaceFormat::R8G8B8A8 even though it's a YUV texture. This is an external texture.
michael@0 40 default:
michael@0 41 if (aFormat >= 0x100 && aFormat <= 0x1FF) {
michael@0 42 // Reserved range for HAL specific formats.
michael@0 43 return gfx::SurfaceFormat::R8G8B8A8;
michael@0 44 } else {
michael@0 45 // This is not super-unreachable, there's a bunch of hypothetical pixel
michael@0 46 // formats we don't deal with.
michael@0 47 // We only want to abort in debug builds here, since if we crash here
michael@0 48 // we'll take down the compositor process and thus the phone. This seems
michael@0 49 // like undesirable behaviour. We'd rather have a subtle artifact.
michael@0 50 printf_stderr(" xxxxx unknow android format %i\n", (int)aFormat);
michael@0 51 MOZ_ASSERT(false, "Unknown Android pixel format.");
michael@0 52 return gfx::SurfaceFormat::UNKNOWN;
michael@0 53 }
michael@0 54 }
michael@0 55 }
michael@0 56
michael@0 57 static GLenum
michael@0 58 TextureTargetForAndroidPixelFormat(android::PixelFormat aFormat)
michael@0 59 {
michael@0 60 switch (aFormat) {
michael@0 61 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
michael@0 62 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
michael@0 63 case HAL_PIXEL_FORMAT_YCbCr_422_I:
michael@0 64 case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
michael@0 65 case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
michael@0 66 case HAL_PIXEL_FORMAT_YV12:
michael@0 67 return LOCAL_GL_TEXTURE_EXTERNAL;
michael@0 68 case android::PIXEL_FORMAT_BGRA_8888:
michael@0 69 case android::PIXEL_FORMAT_RGBA_8888:
michael@0 70 case android::PIXEL_FORMAT_RGBX_8888:
michael@0 71 case android::PIXEL_FORMAT_RGB_565:
michael@0 72 return LOCAL_GL_TEXTURE_2D;
michael@0 73 default:
michael@0 74 if (aFormat >= 0x100 && aFormat <= 0x1FF) {
michael@0 75 // Reserved range for HAL specific formats.
michael@0 76 return LOCAL_GL_TEXTURE_EXTERNAL;
michael@0 77 } else {
michael@0 78 // This is not super-unreachable, there's a bunch of hypothetical pixel
michael@0 79 // formats we don't deal with.
michael@0 80 // We only want to abort in debug builds here, since if we crash here
michael@0 81 // we'll take down the compositor process and thus the phone. This seems
michael@0 82 // like undesirable behaviour. We'd rather have a subtle artifact.
michael@0 83 MOZ_ASSERT(false, "Unknown Android pixel format.");
michael@0 84 return LOCAL_GL_TEXTURE_EXTERNAL;
michael@0 85 }
michael@0 86 }
michael@0 87 }
michael@0 88
michael@0 89 GrallocTextureSourceOGL::GrallocTextureSourceOGL(CompositorOGL* aCompositor,
michael@0 90 android::GraphicBuffer* aGraphicBuffer,
michael@0 91 gfx::SurfaceFormat aFormat)
michael@0 92 : mCompositor(aCompositor)
michael@0 93 , mGraphicBuffer(aGraphicBuffer)
michael@0 94 , mEGLImage(0)
michael@0 95 , mFormat(aFormat)
michael@0 96 , mNeedsReset(true)
michael@0 97 {
michael@0 98 MOZ_ASSERT(mGraphicBuffer.get());
michael@0 99 }
michael@0 100
michael@0 101 GrallocTextureSourceOGL::~GrallocTextureSourceOGL()
michael@0 102 {
michael@0 103 DeallocateDeviceData();
michael@0 104 mCompositor = nullptr;
michael@0 105 }
michael@0 106
michael@0 107 void
michael@0 108 GrallocTextureSourceOGL::BindTexture(GLenum aTextureUnit, gfx::Filter aFilter)
michael@0 109 {
michael@0 110 /*
michael@0 111 * The job of this function is to ensure that the texture is tied to the
michael@0 112 * android::GraphicBuffer, so that texturing will source the GraphicBuffer.
michael@0 113 *
michael@0 114 * To this effect we create an EGLImage wrapping this GraphicBuffer,
michael@0 115 * using EGLImageCreateFromNativeBuffer, and then we tie this EGLImage to our
michael@0 116 * texture using fEGLImageTargetTexture2D.
michael@0 117 */
michael@0 118 MOZ_ASSERT(gl());
michael@0 119 if (!IsValid()) {
michael@0 120 return;
michael@0 121 }
michael@0 122 gl()->MakeCurrent();
michael@0 123
michael@0 124 GLuint tex = GetGLTexture();
michael@0 125 GLuint textureTarget = GetTextureTarget();
michael@0 126
michael@0 127 gl()->fActiveTexture(aTextureUnit);
michael@0 128 gl()->fBindTexture(textureTarget, tex);
michael@0 129
michael@0 130 if (mCompositableBackendData) {
michael@0 131 // There are two paths for locking/unlocking - if mCompositableBackendData is
michael@0 132 // set, we use the texture on there, otherwise we use
michael@0 133 // CompositorBackendSpecificData from the compositor and bind the EGLImage
michael@0 134 // only in Lock().
michael@0 135 if (!mEGLImage) {
michael@0 136 mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer());
michael@0 137 }
michael@0 138 gl()->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
michael@0 139 }
michael@0 140
michael@0 141 ApplyFilterToBoundTexture(gl(), aFilter, textureTarget);
michael@0 142 }
michael@0 143
michael@0 144 void GrallocTextureSourceOGL::Lock()
michael@0 145 {
michael@0 146 if (mCompositableBackendData) return;
michael@0 147
michael@0 148 MOZ_ASSERT(IsValid());
michael@0 149
michael@0 150 mTexture = mCompositor->GetTemporaryTexture(GetTextureTarget(), LOCAL_GL_TEXTURE0);
michael@0 151
michael@0 152 GLuint textureTarget = GetTextureTarget();
michael@0 153
michael@0 154 gl()->MakeCurrent();
michael@0 155 gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
michael@0 156 gl()->fBindTexture(textureTarget, mTexture);
michael@0 157 if (!mEGLImage) {
michael@0 158 mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer());
michael@0 159 }
michael@0 160 gl()->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
michael@0 161 }
michael@0 162
michael@0 163 bool
michael@0 164 GrallocTextureSourceOGL::IsValid() const
michael@0 165 {
michael@0 166 return !!gl() && !!mGraphicBuffer.get() && (!!mCompositor || !!mCompositableBackendData);
michael@0 167 }
michael@0 168
michael@0 169 gl::GLContext*
michael@0 170 GrallocTextureSourceOGL::gl() const
michael@0 171 {
michael@0 172 return mCompositor ? mCompositor->gl() : nullptr;
michael@0 173 }
michael@0 174
michael@0 175 void
michael@0 176 GrallocTextureSourceOGL::SetCompositor(Compositor* aCompositor)
michael@0 177 {
michael@0 178 if (mCompositor && !aCompositor) {
michael@0 179 DeallocateDeviceData();
michael@0 180 }
michael@0 181 mCompositor = static_cast<CompositorOGL*>(aCompositor);
michael@0 182 }
michael@0 183
michael@0 184
michael@0 185 GLenum
michael@0 186 GrallocTextureSourceOGL::GetTextureTarget() const
michael@0 187 {
michael@0 188 MOZ_ASSERT(gl());
michael@0 189 MOZ_ASSERT(mGraphicBuffer.get());
michael@0 190
michael@0 191 if (!gl() || !mGraphicBuffer.get()) {
michael@0 192 return LOCAL_GL_TEXTURE_EXTERNAL;
michael@0 193 }
michael@0 194
michael@0 195 // SGX has a quirk that only TEXTURE_EXTERNAL works and any other value will
michael@0 196 // result in black pixels when trying to draw from bound textures.
michael@0 197 // Unfortunately, using TEXTURE_EXTERNAL on Adreno has a terrible effect on
michael@0 198 // performance.
michael@0 199 // See Bug 950050.
michael@0 200 if (gl()->Renderer() == gl::GLRenderer::SGX530 ||
michael@0 201 gl()->Renderer() == gl::GLRenderer::SGX540) {
michael@0 202 return LOCAL_GL_TEXTURE_EXTERNAL;
michael@0 203 }
michael@0 204
michael@0 205 return TextureTargetForAndroidPixelFormat(mGraphicBuffer->getPixelFormat());
michael@0 206 }
michael@0 207
michael@0 208 void
michael@0 209 GrallocTextureSourceOGL::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
michael@0 210 {
michael@0 211 if (!aBackendData) {
michael@0 212 mCompositableBackendData = nullptr;
michael@0 213 DeallocateDeviceData();
michael@0 214 return;
michael@0 215 }
michael@0 216
michael@0 217 if (mCompositableBackendData != aBackendData) {
michael@0 218 mNeedsReset = true;
michael@0 219 }
michael@0 220
michael@0 221 if (!mNeedsReset) {
michael@0 222 // Update binding to the EGLImage
michael@0 223 gl()->MakeCurrent();
michael@0 224 GLuint tex = GetGLTexture();
michael@0 225 GLuint textureTarget = GetTextureTarget();
michael@0 226 gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
michael@0 227 gl()->fBindTexture(textureTarget, tex);
michael@0 228 gl()->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
michael@0 229 return;
michael@0 230 }
michael@0 231
michael@0 232 mCompositableBackendData = aBackendData;
michael@0 233
michael@0 234 if (!mCompositor) {
michael@0 235 return;
michael@0 236 }
michael@0 237
michael@0 238 // delete old EGLImage
michael@0 239 DeallocateDeviceData();
michael@0 240
michael@0 241 gl()->MakeCurrent();
michael@0 242 GLuint tex = GetGLTexture();
michael@0 243 GLuint textureTarget = GetTextureTarget();
michael@0 244
michael@0 245 gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
michael@0 246 gl()->fBindTexture(textureTarget, tex);
michael@0 247 // create new EGLImage
michael@0 248 mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer());
michael@0 249 gl()->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
michael@0 250 mNeedsReset = false;
michael@0 251 }
michael@0 252
michael@0 253 gfx::IntSize
michael@0 254 GrallocTextureSourceOGL::GetSize() const
michael@0 255 {
michael@0 256 if (!IsValid()) {
michael@0 257 NS_WARNING("Trying to access the size of an invalid GrallocTextureSourceOGL");
michael@0 258 return gfx::IntSize(0, 0);
michael@0 259 }
michael@0 260 return gfx::IntSize(mGraphicBuffer->getWidth(), mGraphicBuffer->getHeight());
michael@0 261 }
michael@0 262
michael@0 263 void
michael@0 264 GrallocTextureSourceOGL::DeallocateDeviceData()
michael@0 265 {
michael@0 266 if (mEGLImage) {
michael@0 267 MOZ_ASSERT(gl());
michael@0 268 gl()->MakeCurrent();
michael@0 269 EGLImageDestroy(gl(), mEGLImage);
michael@0 270 mEGLImage = EGL_NO_IMAGE;
michael@0 271 }
michael@0 272 }
michael@0 273
michael@0 274 GrallocTextureHostOGL::GrallocTextureHostOGL(TextureFlags aFlags,
michael@0 275 const NewSurfaceDescriptorGralloc& aDescriptor)
michael@0 276 : TextureHost(aFlags)
michael@0 277 {
michael@0 278 android::GraphicBuffer* graphicBuffer = nullptr;
michael@0 279 gfx::SurfaceFormat format = gfx::SurfaceFormat::UNKNOWN;
michael@0 280
michael@0 281 mSize = aDescriptor.size();
michael@0 282 mGrallocActor =
michael@0 283 static_cast<GrallocBufferActor*>(aDescriptor.bufferParent());
michael@0 284
michael@0 285 if (mGrallocActor) {
michael@0 286 mGrallocActor->AddTextureHost(this);
michael@0 287 graphicBuffer = mGrallocActor->GetGraphicBuffer();
michael@0 288 }
michael@0 289
michael@0 290 if (graphicBuffer) {
michael@0 291 format =
michael@0 292 SurfaceFormatForAndroidPixelFormat(graphicBuffer->getPixelFormat(),
michael@0 293 aFlags & TEXTURE_RB_SWAPPED);
michael@0 294 }
michael@0 295 mTextureSource = new GrallocTextureSourceOGL(nullptr,
michael@0 296 graphicBuffer,
michael@0 297 format);
michael@0 298 }
michael@0 299
michael@0 300 GrallocTextureHostOGL::~GrallocTextureHostOGL()
michael@0 301 {
michael@0 302 mTextureSource = nullptr;
michael@0 303 if (mGrallocActor) {
michael@0 304 mGrallocActor->RemoveTextureHost();
michael@0 305 mGrallocActor = nullptr;
michael@0 306 }
michael@0 307 }
michael@0 308
michael@0 309 void
michael@0 310 GrallocTextureHostOGL::SetCompositor(Compositor* aCompositor)
michael@0 311 {
michael@0 312 mTextureSource->SetCompositor(static_cast<CompositorOGL*>(aCompositor));
michael@0 313 }
michael@0 314
michael@0 315 bool
michael@0 316 GrallocTextureHostOGL::Lock()
michael@0 317 {
michael@0 318 if (IsValid()) {
michael@0 319 mTextureSource->Lock();
michael@0 320 return true;
michael@0 321 }
michael@0 322 return false;
michael@0 323 }
michael@0 324
michael@0 325 void
michael@0 326 GrallocTextureHostOGL::Unlock()
michael@0 327 {
michael@0 328 // Unlock is done internally by binding the texture to another gralloc buffer
michael@0 329 }
michael@0 330
michael@0 331 bool
michael@0 332 GrallocTextureHostOGL::IsValid() const
michael@0 333 {
michael@0 334 return mTextureSource->IsValid();
michael@0 335 }
michael@0 336
michael@0 337 gfx::SurfaceFormat
michael@0 338 GrallocTextureHostOGL::GetFormat() const
michael@0 339 {
michael@0 340 return mTextureSource->GetFormat();
michael@0 341 }
michael@0 342
michael@0 343 void
michael@0 344 GrallocTextureHostOGL::DeallocateSharedData()
michael@0 345 {
michael@0 346 if (mTextureSource) {
michael@0 347 mTextureSource->ForgetBuffer();
michael@0 348 }
michael@0 349 if (mGrallocActor) {
michael@0 350 PGrallocBufferParent::Send__delete__(mGrallocActor);
michael@0 351 }
michael@0 352 }
michael@0 353
michael@0 354 void
michael@0 355 GrallocTextureHostOGL::ForgetSharedData()
michael@0 356 {
michael@0 357 if (mTextureSource) {
michael@0 358 mTextureSource->ForgetBuffer();
michael@0 359 }
michael@0 360 }
michael@0 361
michael@0 362 void
michael@0 363 GrallocTextureHostOGL::DeallocateDeviceData()
michael@0 364 {
michael@0 365 mTextureSource->DeallocateDeviceData();
michael@0 366 }
michael@0 367
michael@0 368 LayerRenderState
michael@0 369 GrallocTextureHostOGL::GetRenderState()
michael@0 370 {
michael@0 371 if (IsValid()) {
michael@0 372 uint32_t flags = 0;
michael@0 373 if (mFlags & TEXTURE_NEEDS_Y_FLIP) {
michael@0 374 flags |= LAYER_RENDER_STATE_Y_FLIPPED;
michael@0 375 }
michael@0 376 if (mFlags & TEXTURE_RB_SWAPPED) {
michael@0 377 flags |= LAYER_RENDER_STATE_FORMAT_RB_SWAP;
michael@0 378 }
michael@0 379 return LayerRenderState(mTextureSource->mGraphicBuffer.get(),
michael@0 380 gfx::ThebesIntSize(mSize),
michael@0 381 flags,
michael@0 382 this);
michael@0 383 }
michael@0 384
michael@0 385 return LayerRenderState();
michael@0 386 }
michael@0 387
michael@0 388 TemporaryRef<gfx::DataSourceSurface>
michael@0 389 GrallocTextureHostOGL::GetAsSurface() {
michael@0 390 return mTextureSource ? mTextureSource->GetAsSurface()
michael@0 391 : nullptr;
michael@0 392 }
michael@0 393
michael@0 394 TemporaryRef<gfx::DataSourceSurface>
michael@0 395 GrallocTextureSourceOGL::GetAsSurface() {
michael@0 396 if (!IsValid()) {
michael@0 397 return nullptr;
michael@0 398 }
michael@0 399 gl()->MakeCurrent();
michael@0 400
michael@0 401 GLuint tex = GetGLTexture();
michael@0 402 gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
michael@0 403 gl()->fBindTexture(GetTextureTarget(), tex);
michael@0 404 if (!mEGLImage) {
michael@0 405 mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer());
michael@0 406 }
michael@0 407 gl()->fEGLImageTargetTexture2D(GetTextureTarget(), mEGLImage);
michael@0 408
michael@0 409 RefPtr<gfx::DataSourceSurface> surf =
michael@0 410 IsValid() ? ReadBackSurface(gl(), tex, false, GetFormat())
michael@0 411 : nullptr;
michael@0 412
michael@0 413 gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
michael@0 414 return surf.forget();
michael@0 415 }
michael@0 416
michael@0 417 GLuint
michael@0 418 GrallocTextureSourceOGL::GetGLTexture()
michael@0 419 {
michael@0 420 if (mCompositableBackendData) {
michael@0 421 mCompositableBackendData->SetCompositor(mCompositor);
michael@0 422 return static_cast<CompositableDataGonkOGL*>(mCompositableBackendData.get())->GetTexture();
michael@0 423 }
michael@0 424
michael@0 425 return mTexture;
michael@0 426 }
michael@0 427
michael@0 428 void
michael@0 429 GrallocTextureHostOGL::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
michael@0 430 {
michael@0 431 mCompositableBackendData = aBackendData;
michael@0 432 if (mTextureSource) {
michael@0 433 mTextureSource->SetCompositableBackendSpecificData(aBackendData);
michael@0 434 }
michael@0 435 // Register this object to CompositableBackendSpecificData
michael@0 436 // as current TextureHost.
michael@0 437 if (aBackendData) {
michael@0 438 aBackendData->SetCurrentReleaseFenceTexture(this);
michael@0 439 }
michael@0 440 }
michael@0 441
michael@0 442 } // namepsace layers
michael@0 443 } // namepsace mozilla

mercurial