Bug 1699062 - Flatten toolkit/themes/*/global/alerts/. r=desktop-theme-reviewers,dao
[gecko.git] / gfx / webrender_bindings / RenderAndroidSurfaceTextureHost.cpp
blobd8e2378e18e5cc12c17cf16c8f007faf485dca91
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "RenderAndroidSurfaceTextureHost.h"
9 #include "GLReadTexImageHelper.h"
10 #include "mozilla/gfx/Logging.h"
11 #include "mozilla/webrender/RenderThread.h"
12 #include "GLContext.h"
14 namespace mozilla {
15 namespace wr {
17 RenderAndroidSurfaceTextureHost::RenderAndroidSurfaceTextureHost(
18 const java::GeckoSurfaceTexture::GlobalRef& aSurfTex, gfx::IntSize aSize,
19 gfx::SurfaceFormat aFormat, bool aContinuousUpdate)
20 : mSurfTex(aSurfTex),
21 mSize(aSize),
22 mFormat(aFormat),
23 mContinuousUpdate(aContinuousUpdate),
24 mPrepareStatus(STATUS_NONE),
25 mAttachedToGLContext(false) {
26 MOZ_COUNT_CTOR_INHERITED(RenderAndroidSurfaceTextureHost, RenderTextureHost);
28 if (mSurfTex) {
29 mSurfTex->IncrementUse();
33 RenderAndroidSurfaceTextureHost::~RenderAndroidSurfaceTextureHost() {
34 MOZ_ASSERT(RenderThread::IsInRenderThread());
35 MOZ_COUNT_DTOR_INHERITED(RenderAndroidSurfaceTextureHost, RenderTextureHost);
36 // The SurfaceTexture gets destroyed when its use count reaches zero.
37 if (mSurfTex) {
38 mSurfTex->DecrementUse();
42 wr::WrExternalImage RenderAndroidSurfaceTextureHost::Lock(
43 uint8_t aChannelIndex, gl::GLContext* aGL, wr::ImageRendering aRendering) {
44 MOZ_ASSERT(aChannelIndex == 0);
45 MOZ_ASSERT((mPrepareStatus == STATUS_PREPARED) ||
46 (!mSurfTex->IsSingleBuffer() &&
47 mPrepareStatus == STATUS_UPDATE_TEX_IMAGE_NEEDED));
49 if (mGL.get() != aGL) {
50 // This should not happen. On android, SingletonGL is used.
51 MOZ_ASSERT_UNREACHABLE("Unexpected GL context");
52 return InvalidToWrExternalImage();
55 if (!mSurfTex || !mGL || !mGL->MakeCurrent()) {
56 return InvalidToWrExternalImage();
59 MOZ_ASSERT(mAttachedToGLContext);
60 if (!mAttachedToGLContext) {
61 return InvalidToWrExternalImage();
64 if (IsFilterUpdateNecessary(aRendering)) {
65 // Cache new rendering filter.
66 mCachedRendering = aRendering;
67 ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0,
68 LOCAL_GL_TEXTURE_EXTERNAL_OES,
69 mSurfTex->GetTexName(), aRendering);
72 if (mContinuousUpdate) {
73 MOZ_ASSERT(!mSurfTex->IsSingleBuffer());
74 mSurfTex->UpdateTexImage();
75 } else if (mPrepareStatus == STATUS_UPDATE_TEX_IMAGE_NEEDED) {
76 MOZ_ASSERT(!mSurfTex->IsSingleBuffer());
77 // When SurfaceTexture is not single buffer mode, call UpdateTexImage() once
78 // just before rendering. During playing video, one SurfaceTexture is used
79 // for all RenderAndroidSurfaceTextureHosts of video.
80 mSurfTex->UpdateTexImage();
81 mPrepareStatus = STATUS_PREPARED;
84 return NativeTextureToWrExternalImage(mSurfTex->GetTexName(), 0, 0,
85 mSize.width, mSize.height);
88 void RenderAndroidSurfaceTextureHost::Unlock() {}
90 bool RenderAndroidSurfaceTextureHost::EnsureAttachedToGLContext() {
91 // During handling WebRenderError, GeckoSurfaceTexture should not be attached
92 // to GLContext.
93 if (RenderThread::Get()->IsHandlingWebRenderError()) {
94 return false;
97 if (mAttachedToGLContext) {
98 return true;
101 if (!mGL) {
102 mGL = RenderThread::Get()->SingletonGL();
105 if (!mSurfTex || !mGL || !mGL->MakeCurrent()) {
106 return false;
109 if (!mSurfTex->IsAttachedToGLContext((int64_t)mGL.get())) {
110 GLuint texName;
111 mGL->fGenTextures(1, &texName);
112 ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0,
113 LOCAL_GL_TEXTURE_EXTERNAL_OES, texName,
114 mCachedRendering);
116 if (NS_FAILED(mSurfTex->AttachToGLContext((int64_t)mGL.get(), texName))) {
117 MOZ_ASSERT(0);
118 mGL->fDeleteTextures(1, &texName);
119 return false;
123 mAttachedToGLContext = true;
124 return true;
127 void RenderAndroidSurfaceTextureHost::PrepareForUse() {
128 // When SurfaceTexture is single buffer mode, UpdateTexImage needs to be
129 // called only once for each publish. If UpdateTexImage is called more
130 // than once, it causes hang on puglish side. And UpdateTexImage needs to
131 // be called on render thread, since the SurfaceTexture is consumed on render
132 // thread.
133 MOZ_ASSERT(RenderThread::IsInRenderThread());
134 MOZ_ASSERT(mPrepareStatus == STATUS_NONE);
136 if (mContinuousUpdate || !mSurfTex) {
137 return;
140 mPrepareStatus = STATUS_MIGHT_BE_USED_BY_WR;
142 if (mSurfTex->IsSingleBuffer()) {
143 EnsureAttachedToGLContext();
144 // When SurfaceTexture is single buffer mode, it is OK to call
145 // UpdateTexImage() here.
146 mSurfTex->UpdateTexImage();
147 mPrepareStatus = STATUS_PREPARED;
151 void RenderAndroidSurfaceTextureHost::NotifyForUse() {
152 MOZ_ASSERT(RenderThread::IsInRenderThread());
154 if (mPrepareStatus == STATUS_MIGHT_BE_USED_BY_WR) {
155 // This happens when SurfaceTexture of video is rendered on WebRender.
156 // There is a case that SurfaceTexture is not rendered on WebRender, instead
157 // it is rendered to WebGL and the SurfaceTexture should not be attached to
158 // gl context of WebRender. It is ugly. But it is same as Compositor
159 // rendering.
160 MOZ_ASSERT(!mSurfTex->IsSingleBuffer());
161 if (!EnsureAttachedToGLContext()) {
162 return;
164 mPrepareStatus = STATUS_UPDATE_TEX_IMAGE_NEEDED;
168 void RenderAndroidSurfaceTextureHost::NotifyNotUsed() {
169 MOZ_ASSERT(RenderThread::IsInRenderThread());
171 if (!mSurfTex) {
172 MOZ_ASSERT(mPrepareStatus == STATUS_NONE);
173 return;
176 if (mSurfTex->IsSingleBuffer()) {
177 MOZ_ASSERT(mPrepareStatus == STATUS_PREPARED);
178 MOZ_ASSERT(mAttachedToGLContext);
179 // Release SurfaceTexture's buffer to client side.
180 mGL->MakeCurrent();
181 mSurfTex->ReleaseTexImage();
182 } else if (mPrepareStatus == STATUS_UPDATE_TEX_IMAGE_NEEDED) {
183 MOZ_ASSERT(mAttachedToGLContext);
184 // This could happen when video frame was skipped. UpdateTexImage() neeeds
185 // to be called for adjusting SurfaceTexture's buffer status.
186 mSurfTex->UpdateTexImage();
189 mPrepareStatus = STATUS_NONE;
192 gfx::SurfaceFormat RenderAndroidSurfaceTextureHost::GetFormat() const {
193 MOZ_ASSERT(mFormat == gfx::SurfaceFormat::R8G8B8A8 ||
194 mFormat == gfx::SurfaceFormat::R8G8B8X8);
196 if (mFormat == gfx::SurfaceFormat::R8G8B8A8) {
197 return gfx::SurfaceFormat::B8G8R8A8;
200 if (mFormat == gfx::SurfaceFormat::R8G8B8X8) {
201 return gfx::SurfaceFormat::B8G8R8X8;
204 gfxCriticalNoteOnce
205 << "Unexpected color format of RenderAndroidSurfaceTextureHost";
207 return gfx::SurfaceFormat::UNKNOWN;
210 already_AddRefed<DataSourceSurface>
211 RenderAndroidSurfaceTextureHost::ReadTexImage() {
212 if (!mGL) {
213 mGL = RenderThread::Get()->SingletonGL();
214 if (!mGL) {
215 return nullptr;
219 /* Allocate resulting image surface */
220 int32_t stride = mSize.width * BytesPerPixel(GetFormat());
221 RefPtr<DataSourceSurface> surf =
222 Factory::CreateDataSourceSurfaceWithStride(mSize, GetFormat(), stride);
223 if (!surf) {
224 return nullptr;
227 layers::ShaderConfigOGL config = layers::ShaderConfigFromTargetAndFormat(
228 LOCAL_GL_TEXTURE_EXTERNAL, mFormat);
229 int shaderConfig = config.mFeatures;
231 bool ret = mGL->ReadTexImageHelper()->ReadTexImage(
232 surf, mSurfTex->GetTexName(), LOCAL_GL_TEXTURE_EXTERNAL, mSize,
233 shaderConfig, /* aYInvert */ false);
234 if (!ret) {
235 return nullptr;
238 return surf.forget();
241 bool RenderAndroidSurfaceTextureHost::MapPlane(RenderCompositor* aCompositor,
242 uint8_t aChannelIndex,
243 PlaneInfo& aPlaneInfo) {
244 RefPtr<gfx::DataSourceSurface> readback = ReadTexImage();
245 if (!readback) {
246 return false;
249 DataSourceSurface::MappedSurface map;
250 if (!readback->Map(DataSourceSurface::MapType::READ, &map)) {
251 return false;
254 mReadback = readback;
255 aPlaneInfo.mSize = mSize;
256 aPlaneInfo.mStride = map.mStride;
257 aPlaneInfo.mData = map.mData;
258 return true;
261 void RenderAndroidSurfaceTextureHost::UnmapPlanes() {
262 if (mReadback) {
263 mReadback->Unmap();
264 mReadback = nullptr;
268 } // namespace wr
269 } // namespace mozilla