c29aa181051f63e93d15d6cc16c07001d1d4c2dc
[gecko.git] / GrallocTextureHost.cpp
blobc29aa181051f63e93d15d6cc16c07001d1d4c2dc
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 "GLContext.h"
7 #include "gfxImageSurface.h"
8 #include "gfx2DGlue.h"
9 #include <ui/GraphicBuffer.h>
10 #include "mozilla/layers/GrallocTextureHost.h"
11 #include "mozilla/layers/CompositorOGL.h"
13 namespace mozilla {
14 namespace layers {
16 using namespace android;
18 static gfx::SurfaceFormat
19 SurfaceFormatForAndroidPixelFormat(android::PixelFormat aFormat,
20 bool swapRB = false)
22 switch (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.
38 default:
39 if (aFormat >= 0x100 && aFormat <= 0x1FF) {
40 // Reserved range for HAL specific formats.
41 return gfx::FORMAT_B8G8R8A8;
42 } else {
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;
55 static GLenum
56 TextureTargetForAndroidPixelFormat(android::PixelFormat aFormat)
58 switch (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;
69 default:
70 if (aFormat >= 0x100 && aFormat <= 0x1FF) {
71 // Reserved range for HAL specific formats.
72 return LOCAL_GL_TEXTURE_EXTERNAL;
73 } else {
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)
90 , mEGLImage(0)
91 , mFormat(aFormat)
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.
106 MOZ_ASSERT(gl());
107 gl()->MakeCurrent();
110 GLuint tex = mCompositor->GetTemporaryTexture(aTextureUnit);
111 GLuint textureTarget = GetTextureTarget();
113 gl()->fActiveTexture(aTextureUnit);
114 gl()->fBindTexture(textureTarget, tex);
115 if (!mEGLImage) {
116 mEGLImage = gl()->CreateEGLImageForNativeBuffer(mGraphicBuffer->getNativeBuffer());
118 gl()->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
119 gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
120 // XXX - Bug 909356
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();
126 bool
127 GrallocTextureSourceOGL::IsValid() const
129 return !!gl() && !!mGraphicBuffer.get();
132 gl::GLContext*
133 GrallocTextureSourceOGL::gl() const
135 return mCompositor ? mCompositor->gl() : nullptr;
138 GLenum
139 GrallocTextureSourceOGL::GetTextureTarget() const
141 MOZ_ASSERT(mGraphicBuffer.get());
142 return TextureTargetForAndroidPixelFormat(mGraphicBuffer->getPixelFormat());
145 gfx::SurfaceFormat
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;
153 return mFormat;
156 gfx::IntSize
157 GrallocTextureSourceOGL::GetSize() const
159 if (!IsValid()) {
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());
166 void
167 GrallocTextureSourceOGL::DeallocateDeviceData()
169 if (mEGLImage) {
170 MOZ_ASSERT(gl());
171 gl()->MakeCurrent();
172 gl()->DestroyEGLImage(mEGLImage);
173 mEGLImage = 0;
177 GrallocTextureHostOGL::GrallocTextureHostOGL(uint64_t aID,
178 TextureFlags aFlags,
179 const NewSurfaceDescriptorGralloc& aDescriptor)
180 : TextureHost(aID, aFlags)
182 mGrallocActor =
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,
192 graphicBuffer,
193 format);
196 GrallocTextureHostOGL::~GrallocTextureHostOGL()
198 if (mTextureSource) {
199 mTextureSource->mGraphicBuffer = nullptr;
200 mTextureSource->SetCompositor(nullptr);
202 mTextureSource = nullptr;
205 void
206 GrallocTextureHostOGL::SetCompositor(Compositor* aCompositor)
208 mTextureSource->SetCompositor(static_cast<CompositorOGL*>(aCompositor));
211 bool
212 GrallocTextureHostOGL::Lock()
214 return IsValid();
217 void
218 GrallocTextureHostOGL::Unlock()
220 // Unlock is done internally by binding the texture to another gralloc buffer
223 bool
224 GrallocTextureHostOGL::IsValid() const
226 return mTextureSource->IsValid();
229 gfx::SurfaceFormat
230 GrallocTextureHostOGL::GetFormat() const
232 return mTextureSource->GetFormat();
235 void
236 GrallocTextureHostOGL::DeallocateSharedData()
238 if (mTextureSource) {
239 mTextureSource->ForgetBuffer();
241 PGrallocBufferParent::Send__delete__(mGrallocActor);
244 void
245 GrallocTextureHostOGL::DeallocateDeviceData()
247 mTextureSource->DeallocateDeviceData();
250 LayerRenderState
251 GrallocTextureHostOGL::GetRenderState()
253 if (IsValid()) {
254 uint32_t flags = 0;
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),
263 flags);
266 return LayerRenderState();
269 already_AddRefed<gfxImageSurface>
270 GrallocTextureHostOGL::GetAsSurface() {
271 return mTextureSource ? mTextureSource->GetAsSurface()
272 : nullptr;
275 already_AddRefed<gfxImageSurface>
276 GrallocTextureSourceOGL::GetAsSurface() {
277 MOZ_ASSERT(gl());
278 gl()->MakeCurrent();
280 GLuint tex = mCompositor->GetTemporaryTexture(LOCAL_GL_TEXTURE0);
281 gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
282 gl()->fBindTexture(GetTextureTarget(), tex);
283 if (!mEGLImage) {
284 mEGLImage = gl()->CreateEGLImageForNativeBuffer(mGraphicBuffer->getNativeBuffer());
286 gl()->fEGLImageTargetTexture2D(GetTextureTarget(), mEGLImage);
288 nsRefPtr<gfxImageSurface> surf = IsValid() ? gl()->GetTexImage(tex, false, GetFormat())
289 : nullptr;
291 gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
292 return surf.forget();
295 } // namepsace layers
296 } // namepsace mozilla