diff options
Diffstat (limited to 'gfx/webrender_bindings/RenderTextureHostSWGL.cpp')
-rw-r--r-- | gfx/webrender_bindings/RenderTextureHostSWGL.cpp | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/gfx/webrender_bindings/RenderTextureHostSWGL.cpp b/gfx/webrender_bindings/RenderTextureHostSWGL.cpp new file mode 100644 index 0000000000..ad2d960837 --- /dev/null +++ b/gfx/webrender_bindings/RenderTextureHostSWGL.cpp @@ -0,0 +1,231 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "RenderTextureHostSWGL.h" + +#include "mozilla/gfx/Logging.h" +#include "mozilla/layers/TextureHost.h" +#include "RenderThread.h" + +namespace mozilla { +namespace wr { + +bool RenderTextureHostSWGL::UpdatePlanes(RenderCompositor* aCompositor) { + wr_swgl_make_current(mContext); + size_t planeCount = GetPlaneCount(); + bool texInit = false; + if (mPlanes.size() < planeCount) { + mPlanes.reserve(planeCount); + while (mPlanes.size() < planeCount) { + mPlanes.push_back(PlaneInfo(wr_swgl_gen_texture(mContext))); + } + texInit = true; + } + gfx::SurfaceFormat format = GetFormat(); + gfx::ColorDepth colorDepth = GetColorDepth(); + for (size_t i = 0; i < planeCount; i++) { + PlaneInfo& plane = mPlanes[i]; + if (!MapPlane(aCompositor, i, plane)) { + if (i > 0) { + UnmapPlanes(); + } + return false; + } + GLenum internalFormat = 0; + switch (format) { + case gfx::SurfaceFormat::B8G8R8A8: + case gfx::SurfaceFormat::B8G8R8X8: + MOZ_ASSERT(colorDepth == gfx::ColorDepth::COLOR_8); + internalFormat = LOCAL_GL_RGBA8; + break; + case gfx::SurfaceFormat::YUV: + switch (colorDepth) { + case gfx::ColorDepth::COLOR_8: + internalFormat = LOCAL_GL_R8; + break; + case gfx::ColorDepth::COLOR_10: + case gfx::ColorDepth::COLOR_12: + case gfx::ColorDepth::COLOR_16: + internalFormat = LOCAL_GL_R16; + break; + } + break; + case gfx::SurfaceFormat::NV12: + switch (colorDepth) { + case gfx::ColorDepth::COLOR_8: + internalFormat = i > 0 ? LOCAL_GL_RG8 : LOCAL_GL_R8; + break; + case gfx::ColorDepth::COLOR_10: + case gfx::ColorDepth::COLOR_12: + case gfx::ColorDepth::COLOR_16: + internalFormat = i > 0 ? LOCAL_GL_RG16 : LOCAL_GL_R16; + break; + } + break; + case gfx::SurfaceFormat::P010: + MOZ_ASSERT(colorDepth == gfx::ColorDepth::COLOR_10); + internalFormat = i > 0 ? LOCAL_GL_RG16 : LOCAL_GL_R16; + break; + case gfx::SurfaceFormat::YUV422: + MOZ_ASSERT(colorDepth == gfx::ColorDepth::COLOR_8); + internalFormat = LOCAL_GL_RGB_RAW_422_APPLE; + break; + default: + MOZ_RELEASE_ASSERT(false, "Unhandled external image format"); + break; + } + wr_swgl_set_texture_buffer(mContext, plane.mTexture, internalFormat, + plane.mSize.width, plane.mSize.height, + plane.mStride, plane.mData, 0, 0); + } + if (texInit) { + // Initialize the mip filters to linear by default. + for (const auto& plane : mPlanes) { + wr_swgl_set_texture_parameter(mContext, plane.mTexture, + LOCAL_GL_TEXTURE_MIN_FILTER, + LOCAL_GL_LINEAR); + wr_swgl_set_texture_parameter(mContext, plane.mTexture, + LOCAL_GL_TEXTURE_MAG_FILTER, + LOCAL_GL_LINEAR); + } + } + return true; +} + +bool RenderTextureHostSWGL::SetContext(void* aContext) { + if (mContext != aContext) { + CleanupPlanes(); + mContext = aContext; + wr_swgl_reference_context(mContext); + } + return mContext != nullptr; +} + +wr::WrExternalImage RenderTextureHostSWGL::LockSWGL( + uint8_t aChannelIndex, void* aContext, RenderCompositor* aCompositor) { + if (!SetContext(aContext)) { + return InvalidToWrExternalImage(); + } + if (!mLocked) { + if (!UpdatePlanes(aCompositor)) { + return InvalidToWrExternalImage(); + } + mLocked = true; + } + if (aChannelIndex >= mPlanes.size()) { + return InvalidToWrExternalImage(); + } + const PlaneInfo& plane = mPlanes[aChannelIndex]; + + const auto uvs = GetUvCoords(plane.mSize); + + // Prefer native textures, unless our backend forbids it. + // If the GetUvCoords call above returned anything other than the default, + // for example if this is a RenderAndroidSurfaceTextureHost, then this won't + // be handled correctly in the RawDataToWrExternalImage path. But we shouldn't + // hit this path in practice with a RenderAndroidSurfaceTextureHost. + layers::TextureHost::NativeTexturePolicy policy = + layers::TextureHost::BackendNativeTexturePolicy( + layers::WebRenderBackend::SOFTWARE, plane.mSize); + return policy == layers::TextureHost::NativeTexturePolicy::FORBID + ? RawDataToWrExternalImage((uint8_t*)plane.mData, + plane.mStride * plane.mSize.height) + : NativeTextureToWrExternalImage(plane.mTexture, uvs.first.x, + uvs.first.y, uvs.second.x, + uvs.second.y); +} + +void RenderTextureHostSWGL::UnlockSWGL() { + if (mLocked) { + mLocked = false; + UnmapPlanes(); + } +} + +void RenderTextureHostSWGL::CleanupPlanes() { + if (!mContext) { + return; + } + if (!mPlanes.empty()) { + wr_swgl_make_current(mContext); + for (const auto& plane : mPlanes) { + wr_swgl_delete_texture(mContext, plane.mTexture); + } + mPlanes.clear(); + } + wr_swgl_destroy_context(mContext); + mContext = nullptr; +} + +RenderTextureHostSWGL::~RenderTextureHostSWGL() { CleanupPlanes(); } + +bool RenderTextureHostSWGL::LockSWGLCompositeSurface( + void* aContext, wr::SWGLCompositeSurfaceInfo* aInfo) { + if (!SetContext(aContext)) { + return false; + } + if (!mLocked) { + if (!UpdatePlanes(nullptr)) { + return false; + } + mLocked = true; + } + MOZ_ASSERT(mPlanes.size() <= 3); + for (size_t i = 0; i < mPlanes.size(); i++) { + aInfo->textures[i] = mPlanes[i].mTexture; + } + switch (GetFormat()) { + case gfx::SurfaceFormat::YUV: + case gfx::SurfaceFormat::NV12: + case gfx::SurfaceFormat::P010: + case gfx::SurfaceFormat::YUV422: { + aInfo->yuv_planes = mPlanes.size(); + auto colorSpace = GetYUVColorSpace(); + aInfo->color_space = ToWrYuvRangedColorSpace(colorSpace); + auto colorDepth = GetColorDepth(); + aInfo->color_depth = ToWrColorDepth(colorDepth); + break; + } + case gfx::SurfaceFormat::B8G8R8A8: + case gfx::SurfaceFormat::B8G8R8X8: + break; + default: + gfxCriticalNote << "Unhandled external image format: " << GetFormat(); + MOZ_RELEASE_ASSERT(false, "Unhandled external image format"); + break; + } + aInfo->size.width = mPlanes[0].mSize.width; + aInfo->size.height = mPlanes[0].mSize.height; + return true; +} + +bool wr_swgl_lock_composite_surface(void* aContext, wr::ExternalImageId aId, + wr::SWGLCompositeSurfaceInfo* aInfo) { + RenderTextureHost* texture = RenderThread::Get()->GetRenderTexture(aId); + if (!texture) { + return false; + } + RenderTextureHostSWGL* swglTex = texture->AsRenderTextureHostSWGL(); + if (!swglTex) { + return false; + } + return swglTex->LockSWGLCompositeSurface(aContext, aInfo); +} + +void wr_swgl_unlock_composite_surface(void* aContext, wr::ExternalImageId aId) { + RenderTextureHost* texture = RenderThread::Get()->GetRenderTexture(aId); + if (!texture) { + return; + } + RenderTextureHostSWGL* swglTex = texture->AsRenderTextureHostSWGL(); + if (!swglTex) { + return; + } + swglTex->UnlockSWGL(); +} + +} // namespace wr +} // namespace mozilla |