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/. */
7 #include "gfxImageSurface.h"
9 #include <ui/GraphicBuffer.h>
10 #include "mozilla/layers/GrallocTextureHost.h"
11 #include "mozilla/layers/CompositorOGL.h"
16 using namespace android
;
18 static gfx::SurfaceFormat
19 SurfaceFormatForAndroidPixelFormat(android::PixelFormat aFormat
,
23 case android::PIXEL_FORMAT_BGRA_8888
:
24 return swapRB
? gfx::FORMAT_R8G8B8A8
: gfx::FORMAT_B8G8R8A8
;
25 case android::PIXEL_FORMAT_RGBA_8888
:
26 return swapRB
? gfx::FORMAT_B8G8R8A8
: gfx::FORMAT_R8G8B8A8
;
27 case android::PIXEL_FORMAT_RGBX_8888
:
28 return swapRB
? gfx::FORMAT_B8G8R8X8
: gfx::FORMAT_R8G8B8X8
;
29 case android::PIXEL_FORMAT_RGB_565
:
30 return gfx::FORMAT_R5G6B5
;
31 case android::PIXEL_FORMAT_A_8
:
32 return gfx::FORMAT_A8
;
33 case HAL_PIXEL_FORMAT_YCbCr_422_SP
:
34 case HAL_PIXEL_FORMAT_YCrCb_420_SP
:
35 case HAL_PIXEL_FORMAT_YCbCr_422_I
:
36 case HAL_PIXEL_FORMAT_YV12
:
37 return gfx::FORMAT_B8G8R8A8
; // yup, use FORMAT_B8G8R8A8 even though it's a YUV texture. This is an external texture.
39 if (aFormat
>= 0x100 && aFormat
<= 0x1FF) {
40 // Reserved range for HAL specific formats.
41 return gfx::FORMAT_B8G8R8A8
;
43 // This is not super-unreachable, there's a bunch of hypothetical pixel
44 // formats we don't deal with.
45 // We only want to abort in debug builds here, since if we crash here
46 // we'll take down the compositor process and thus the phone. This seems
47 // like undesirable behaviour. We'd rather have a subtle artifact.
48 printf_stderr(" xxxxx unknow android format %i\n", (int)aFormat
);
49 MOZ_ASSERT(false, "Unknown Android pixel format.");
50 return gfx::FORMAT_UNKNOWN
;
56 TextureTargetForAndroidPixelFormat(android::PixelFormat aFormat
)
59 case HAL_PIXEL_FORMAT_YCbCr_422_SP
:
60 case HAL_PIXEL_FORMAT_YCrCb_420_SP
:
61 case HAL_PIXEL_FORMAT_YCbCr_422_I
:
62 case HAL_PIXEL_FORMAT_YV12
:
63 return LOCAL_GL_TEXTURE_EXTERNAL
;
64 case android::PIXEL_FORMAT_RGBA_8888
:
65 case android::PIXEL_FORMAT_RGBX_8888
:
66 case android::PIXEL_FORMAT_RGB_565
:
67 case android::PIXEL_FORMAT_A_8
:
68 return LOCAL_GL_TEXTURE_2D
;
70 if (aFormat
>= 0x100 && aFormat
<= 0x1FF) {
71 // Reserved range for HAL specific formats.
72 return LOCAL_GL_TEXTURE_EXTERNAL
;
74 // This is not super-unreachable, there's a bunch of hypothetical pixel
75 // formats we don't deal with.
76 // We only want to abort in debug builds here, since if we crash here
77 // we'll take down the compositor process and thus the phone. This seems
78 // like undesirable behaviour. We'd rather have a subtle artifact.
79 MOZ_ASSERT(false, "Unknown Android pixel format.");
80 return LOCAL_GL_TEXTURE_EXTERNAL
;
85 GrallocTextureSourceOGL::GrallocTextureSourceOGL(CompositorOGL
* aCompositor
,
86 android::GraphicBuffer
* aGraphicBuffer
,
87 gfx::SurfaceFormat aFormat
)
88 : mCompositor(aCompositor
)
89 , mGraphicBuffer(aGraphicBuffer
)
93 MOZ_ASSERT(mGraphicBuffer
.get());
96 void GrallocTextureSourceOGL::BindTexture(GLenum aTextureUnit
)
99 * The job of this function is to ensure that the texture is tied to the
100 * android::GraphicBuffer, so that texturing will source the GraphicBuffer.
102 * To this effect we create an EGLImage wrapping this GraphicBuffer,
103 * using CreateEGLImageForNativeBuffer, and then we tie this EGLImage to our
104 * texture using fEGLImageTargetTexture2D.
110 GLuint tex
= mCompositor
->GetTemporaryTexture(aTextureUnit
);
111 GLuint textureTarget
= GetTextureTarget();
113 gl()->fActiveTexture(aTextureUnit
);
114 gl()->fBindTexture(textureTarget
, tex
);
116 mEGLImage
= gl()->CreateEGLImageForNativeBuffer(mGraphicBuffer
->getNativeBuffer());
118 gl()->fEGLImageTargetTexture2D(textureTarget
, mEGLImage
);
119 gl()->fActiveTexture(LOCAL_GL_TEXTURE0
);
121 // This is a temporary fix to a bad lock/unlock race with the camera.
122 // It is bad for performances so we need to find a better way asap.
123 DeallocateDeviceData();
127 GrallocTextureSourceOGL::IsValid() const
129 return !!gl() && !!mGraphicBuffer
.get();
133 GrallocTextureSourceOGL::gl() const
135 return mCompositor
? mCompositor
->gl() : nullptr;
139 GrallocTextureSourceOGL::GetTextureTarget() const
141 MOZ_ASSERT(mGraphicBuffer
.get());
142 return TextureTargetForAndroidPixelFormat(mGraphicBuffer
->getPixelFormat());
146 GrallocTextureSourceOGL::GetFormat() const {
147 if (!mGraphicBuffer
.get()) {
148 return gfx::FORMAT_UNKNOWN
;
150 if (GetTextureTarget() == LOCAL_GL_TEXTURE_EXTERNAL
) {
151 return gfx::FORMAT_R8G8B8A8
;
157 GrallocTextureSourceOGL::GetSize() const
160 NS_WARNING("Trying to access the size of an invalid GrallocTextureSourceOGL");
161 return gfx::IntSize(0, 0);
163 return gfx::IntSize(mGraphicBuffer
->getWidth(), mGraphicBuffer
->getHeight());
167 GrallocTextureSourceOGL::DeallocateDeviceData()
172 gl()->DestroyEGLImage(mEGLImage
);
177 GrallocTextureHostOGL::GrallocTextureHostOGL(uint64_t aID
,
179 const NewSurfaceDescriptorGralloc
& aDescriptor
)
180 : TextureHost(aID
, aFlags
)
183 static_cast<GrallocBufferActor
*>(aDescriptor
.bufferParent());
185 android::GraphicBuffer
* graphicBuffer
= mGrallocActor
->GetGraphicBuffer();
187 mSize
= aDescriptor
.size();
188 gfx::SurfaceFormat format
=
189 SurfaceFormatForAndroidPixelFormat(graphicBuffer
->getPixelFormat(),
190 aFlags
& TEXTURE_RB_SWAPPED
);
191 mTextureSource
= new GrallocTextureSourceOGL(nullptr,
196 GrallocTextureHostOGL::~GrallocTextureHostOGL()
198 if (mTextureSource
) {
199 mTextureSource
->mGraphicBuffer
= nullptr;
200 mTextureSource
->SetCompositor(nullptr);
202 mTextureSource
= nullptr;
206 GrallocTextureHostOGL::SetCompositor(Compositor
* aCompositor
)
208 mTextureSource
->SetCompositor(static_cast<CompositorOGL
*>(aCompositor
));
212 GrallocTextureHostOGL::Lock()
218 GrallocTextureHostOGL::Unlock()
220 // Unlock is done internally by binding the texture to another gralloc buffer
224 GrallocTextureHostOGL::IsValid() const
226 return mTextureSource
->IsValid();
230 GrallocTextureHostOGL::GetFormat() const
232 return mTextureSource
->GetFormat();
236 GrallocTextureHostOGL::DeallocateSharedData()
238 if (mTextureSource
) {
239 mTextureSource
->ForgetBuffer();
241 PGrallocBufferParent::Send__delete__(mGrallocActor
);
245 GrallocTextureHostOGL::DeallocateDeviceData()
247 mTextureSource
->DeallocateDeviceData();
251 GrallocTextureHostOGL::GetRenderState()
255 if (mFlags
& TEXTURE_NEEDS_Y_FLIP
) {
256 flags
|= LAYER_RENDER_STATE_Y_FLIPPED
;
258 if (mFlags
& TEXTURE_RB_SWAPPED
) {
259 flags
|= LAYER_RENDER_STATE_FORMAT_RB_SWAP
;
261 return LayerRenderState(mTextureSource
->mGraphicBuffer
.get(),
262 gfx::ThebesIntSize(mSize
),
266 return LayerRenderState();
269 already_AddRefed
<gfxImageSurface
>
270 GrallocTextureHostOGL::GetAsSurface() {
271 return mTextureSource
? mTextureSource
->GetAsSurface()
275 already_AddRefed
<gfxImageSurface
>
276 GrallocTextureSourceOGL::GetAsSurface() {
280 GLuint tex
= mCompositor
->GetTemporaryTexture(LOCAL_GL_TEXTURE0
);
281 gl()->fActiveTexture(LOCAL_GL_TEXTURE0
);
282 gl()->fBindTexture(GetTextureTarget(), tex
);
284 mEGLImage
= gl()->CreateEGLImageForNativeBuffer(mGraphicBuffer
->getNativeBuffer());
286 gl()->fEGLImageTargetTexture2D(GetTextureTarget(), mEGLImage
);
288 nsRefPtr
<gfxImageSurface
> surf
= IsValid() ? gl()->GetTexImage(tex
, false, GetFormat())
291 gl()->fActiveTexture(LOCAL_GL_TEXTURE0
);
292 return surf
.forget();
295 } // namepsace layers
296 } // namepsace mozilla