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 "RenderTextureHostSWGL.h"
9 #include "mozilla/gfx/Logging.h"
10 #include "mozilla/layers/TextureHost.h"
11 #include "RenderThread.h"
16 bool RenderTextureHostSWGL::UpdatePlanes(RenderCompositor
* aCompositor
) {
17 wr_swgl_make_current(mContext
);
18 size_t planeCount
= GetPlaneCount();
20 if (mPlanes
.size() < planeCount
) {
21 mPlanes
.reserve(planeCount
);
22 while (mPlanes
.size() < planeCount
) {
23 mPlanes
.push_back(PlaneInfo(wr_swgl_gen_texture(mContext
)));
27 gfx::SurfaceFormat format
= GetFormat();
28 gfx::ColorDepth colorDepth
= GetColorDepth();
29 for (size_t i
= 0; i
< planeCount
; i
++) {
30 PlaneInfo
& plane
= mPlanes
[i
];
31 if (!MapPlane(aCompositor
, i
, plane
)) {
37 GLenum internalFormat
= 0;
39 case gfx::SurfaceFormat::B8G8R8A8
:
40 case gfx::SurfaceFormat::B8G8R8X8
:
41 MOZ_ASSERT(colorDepth
== gfx::ColorDepth::COLOR_8
);
42 internalFormat
= LOCAL_GL_RGBA8
;
44 case gfx::SurfaceFormat::YUV
:
46 case gfx::ColorDepth::COLOR_8
:
47 internalFormat
= LOCAL_GL_R8
;
49 case gfx::ColorDepth::COLOR_10
:
50 case gfx::ColorDepth::COLOR_12
:
51 case gfx::ColorDepth::COLOR_16
:
52 internalFormat
= LOCAL_GL_R16
;
56 case gfx::SurfaceFormat::NV12
:
58 case gfx::ColorDepth::COLOR_8
:
59 internalFormat
= i
> 0 ? LOCAL_GL_RG8
: LOCAL_GL_R8
;
61 case gfx::ColorDepth::COLOR_10
:
62 case gfx::ColorDepth::COLOR_12
:
63 case gfx::ColorDepth::COLOR_16
:
64 internalFormat
= i
> 0 ? LOCAL_GL_RG16
: LOCAL_GL_R16
;
68 case gfx::SurfaceFormat::P010
:
69 MOZ_ASSERT(colorDepth
== gfx::ColorDepth::COLOR_10
);
70 internalFormat
= i
> 0 ? LOCAL_GL_RG16
: LOCAL_GL_R16
;
72 case gfx::SurfaceFormat::YUV422
:
73 MOZ_ASSERT(colorDepth
== gfx::ColorDepth::COLOR_8
);
74 internalFormat
= LOCAL_GL_RGB_RAW_422_APPLE
;
77 MOZ_RELEASE_ASSERT(false, "Unhandled external image format");
80 wr_swgl_set_texture_buffer(mContext
, plane
.mTexture
, internalFormat
,
81 plane
.mSize
.width
, plane
.mSize
.height
,
82 plane
.mStride
, plane
.mData
, 0, 0);
85 // Initialize the mip filters to linear by default.
86 for (const auto& plane
: mPlanes
) {
87 wr_swgl_set_texture_parameter(mContext
, plane
.mTexture
,
88 LOCAL_GL_TEXTURE_MIN_FILTER
,
90 wr_swgl_set_texture_parameter(mContext
, plane
.mTexture
,
91 LOCAL_GL_TEXTURE_MAG_FILTER
,
98 bool RenderTextureHostSWGL::SetContext(void* aContext
) {
99 if (mContext
!= aContext
) {
102 wr_swgl_reference_context(mContext
);
104 return mContext
!= nullptr;
107 wr::WrExternalImage
RenderTextureHostSWGL::LockSWGL(
108 uint8_t aChannelIndex
, void* aContext
, RenderCompositor
* aCompositor
) {
109 if (!SetContext(aContext
)) {
110 return InvalidToWrExternalImage();
113 if (!UpdatePlanes(aCompositor
)) {
114 return InvalidToWrExternalImage();
118 if (aChannelIndex
>= mPlanes
.size()) {
119 return InvalidToWrExternalImage();
121 const PlaneInfo
& plane
= mPlanes
[aChannelIndex
];
123 const auto uvs
= GetUvCoords(plane
.mSize
);
125 // Prefer native textures, unless our backend forbids it.
126 // If the GetUvCoords call above returned anything other than the default,
127 // for example if this is a RenderAndroidSurfaceTextureHost, then this won't
128 // be handled correctly in the RawDataToWrExternalImage path. But we shouldn't
129 // hit this path in practice with a RenderAndroidSurfaceTextureHost.
130 layers::TextureHost::NativeTexturePolicy policy
=
131 layers::TextureHost::BackendNativeTexturePolicy(
132 layers::WebRenderBackend::SOFTWARE
, plane
.mSize
);
133 return policy
== layers::TextureHost::NativeTexturePolicy::FORBID
134 ? RawDataToWrExternalImage((uint8_t*)plane
.mData
,
135 plane
.mStride
* plane
.mSize
.height
)
136 : NativeTextureToWrExternalImage(plane
.mTexture
, uvs
.first
.x
,
137 uvs
.first
.y
, uvs
.second
.x
,
141 void RenderTextureHostSWGL::UnlockSWGL() {
148 void RenderTextureHostSWGL::CleanupPlanes() {
152 if (!mPlanes
.empty()) {
153 wr_swgl_make_current(mContext
);
154 for (const auto& plane
: mPlanes
) {
155 wr_swgl_delete_texture(mContext
, plane
.mTexture
);
159 wr_swgl_destroy_context(mContext
);
163 RenderTextureHostSWGL::~RenderTextureHostSWGL() { CleanupPlanes(); }
165 bool RenderTextureHostSWGL::LockSWGLCompositeSurface(
166 void* aContext
, wr::SWGLCompositeSurfaceInfo
* aInfo
) {
167 if (!SetContext(aContext
)) {
171 if (!UpdatePlanes(nullptr)) {
176 MOZ_ASSERT(mPlanes
.size() <= 3);
177 for (size_t i
= 0; i
< mPlanes
.size(); i
++) {
178 aInfo
->textures
[i
] = mPlanes
[i
].mTexture
;
180 switch (GetFormat()) {
181 case gfx::SurfaceFormat::YUV
:
182 case gfx::SurfaceFormat::NV12
:
183 case gfx::SurfaceFormat::P010
:
184 case gfx::SurfaceFormat::YUV422
: {
185 aInfo
->yuv_planes
= mPlanes
.size();
186 auto colorSpace
= GetYUVColorSpace();
187 aInfo
->color_space
= ToWrYuvRangedColorSpace(colorSpace
);
188 auto colorDepth
= GetColorDepth();
189 aInfo
->color_depth
= ToWrColorDepth(colorDepth
);
192 case gfx::SurfaceFormat::B8G8R8A8
:
193 case gfx::SurfaceFormat::B8G8R8X8
:
196 gfxCriticalNote
<< "Unhandled external image format: " << GetFormat();
197 MOZ_RELEASE_ASSERT(false, "Unhandled external image format");
200 aInfo
->size
.width
= mPlanes
[0].mSize
.width
;
201 aInfo
->size
.height
= mPlanes
[0].mSize
.height
;
205 bool wr_swgl_lock_composite_surface(void* aContext
, wr::ExternalImageId aId
,
206 wr::SWGLCompositeSurfaceInfo
* aInfo
) {
207 RenderTextureHost
* texture
= RenderThread::Get()->GetRenderTexture(aId
);
211 RenderTextureHostSWGL
* swglTex
= texture
->AsRenderTextureHostSWGL();
215 return swglTex
->LockSWGLCompositeSurface(aContext
, aInfo
);
218 void wr_swgl_unlock_composite_surface(void* aContext
, wr::ExternalImageId aId
) {
219 RenderTextureHost
* texture
= RenderThread::Get()->GetRenderTexture(aId
);
223 RenderTextureHostSWGL
* swglTex
= texture
->AsRenderTextureHostSWGL();
227 swglTex
->UnlockSWGL();
231 } // namespace mozilla