#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "media/renderers/paint_canvas_video_renderer.h"
#include <GLES3/gl3.h>
#include <array>
#include <limits>
#include <numeric>
#include "base/barrier_closure.h"
#include "base/compiler_specific.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/numerics/checked_math.h"
#include "base/sequence_checker.h"
#include "base/synchronization/waitable_event.h"
#include "base/system/sys_info.h"
#include "base/task/thread_pool.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "cc/paint/paint_canvas.h"
#include "cc/paint/paint_flags.h"
#include "cc/paint/paint_image_builder.h"
#include "components/viz/common/gpu/raster_context_provider.h"
#include "components/viz/common/resources/shared_image_format.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/client_shared_image.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/client/raster_interface.h"
#include "gpu/command_buffer/client/shared_image_interface.h"
#include "gpu/command_buffer/common/capabilities.h"
#include "gpu/command_buffer/common/mailbox_holder.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "media/base/data_buffer.h"
#include "media/base/video_frame.h"
#include "media/base/wait_and_replace_sync_token_client.h"
#include "media/renderers/video_frame_yuv_mailboxes_holder.h"
#include "third_party/libyuv/include/libyuv.h"
#include "third_party/skia/include/core/SkColorSpace.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkImageGenerator.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
#include "third_party/skia/include/gpu/ganesh/SkImageGanesh.h"
#include "third_party/skia/include/gpu/ganesh/gl/GrGLBackendSurface.h"
#include "third_party/skia/include/gpu/gl/GrGLTypes.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/skia_conversions.h"
#if SK_B32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_R32_SHIFT == 16 && \
SK_A32_SHIFT == 24
#define OUTPUT_ARGB …
#define LIBYUV_ABGR_TO_ARGB …
#define YUV_MATRIX(matrix) …
#define YUV_ORDER(y, y_stride, u, u_stride, v, v_stride) …
#define GBR_TO_RGB_ORDER(y, y_stride, u, u_stride, v, v_stride) …
#define LIBYUV_NV12_TO_ARGB_MATRIX …
#define SHARED_IMAGE_FORMAT …
#elif SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16 && \
SK_A32_SHIFT == 24
#define OUTPUT_ARGB …
#define LIBYUV_ABGR_TO_ARGB …
#define YUV_MATRIX …
#define YUV_ORDER …
#define GBR_TO_RGB_ORDER …
#define LIBYUV_NV12_TO_ARGB_MATRIX …
#define SHARED_IMAGE_FORMAT …
#else
#error Unexpected Skia ARGB_8888 layout!
#endif
namespace media {
namespace {
const int kTemporaryResourceDeletionDelay = …;
class ScopedSharedImageAccess { … };
const gpu::MailboxHolder& GetVideoFrameMailboxHolder(VideoFrame* video_frame) { … }
sk_sp<SkImage> WrapGLTexture(
GLenum target,
GLuint texture_id,
const gfx::Size& size,
viz::RasterContextProvider* raster_context_provider,
bool texture_origin_is_top_left) { … }
void BindAndTexImage2D(gpu::gles2::GLES2Interface* gl,
unsigned int target,
unsigned int texture,
unsigned int internal_format,
unsigned int format,
unsigned int type,
int level,
const gfx::Size& size) { … }
void CopyMailboxToTexture(gpu::gles2::GLES2Interface* gl,
const gfx::Size& coded_size,
const gfx::Rect& visible_rect,
const gpu::Mailbox& source_mailbox,
const gpu::SyncToken& source_sync_token,
unsigned int target,
unsigned int texture,
unsigned int internal_format,
unsigned int format,
unsigned int type,
int level,
bool premultiply_alpha,
bool flip_y) { … }
void SynchronizeVideoFrameRead(scoped_refptr<VideoFrame> video_frame,
gpu::raster::RasterInterface* ri,
gpu::ContextSupport* context_support) { … }
void SynchronizeVideoFrameRead(scoped_refptr<VideoFrame> video_frame,
gpu::gles2::GLES2Interface* gl,
gpu::ContextSupport* context_support) { … }
const libyuv::YuvConstants* GetYuvContantsForColorSpace(SkYUVColorSpace cs) { … }
libyuv::FilterMode ToLibyuvFilterMode(
PaintCanvasVideoRenderer::FilterMode filter) { … }
size_t NumConvertVideoFrameToRGBPixelsTasks(const VideoFrame* video_frame) { … }
void ConvertVideoFrameToRGBPixelsTask(const VideoFrame* video_frame,
void* rgb_pixels,
size_t row_bytes,
bool premultiply_alpha,
libyuv::FilterMode filter,
size_t task_index,
size_t n_tasks,
base::RepeatingClosure* done) { … }
#if !BUILDFLAG(IS_ANDROID)
bool ValidFormatForDirectUploading(
viz::RasterContextProvider* raster_context_provider,
GrGLenum format,
unsigned int type) { … }
#endif
std::tuple<SkYUVAInfo::PlaneConfig, SkYUVAInfo::Subsampling>
VideoPixelFormatAsSkYUVAInfoValues(VideoPixelFormat format) { … }
#if !BUILDFLAG(IS_ANDROID)
BASE_FEATURE(…);
#endif
}
class VideoImageGenerator : public cc::PaintImageGenerator { … };
class VideoTextureBacking : public cc::TextureBacking { … };
PaintCanvasVideoRenderer::PaintCanvasVideoRenderer()
: … { … }
PaintCanvasVideoRenderer::~PaintCanvasVideoRenderer() = default;
void PaintCanvasVideoRenderer::Paint(
scoped_refptr<VideoFrame> video_frame,
cc::PaintCanvas* canvas,
const gfx::RectF& dest_rect,
cc::PaintFlags& flags,
VideoTransformation video_transformation,
viz::RasterContextProvider* raster_context_provider) { … }
void PaintCanvasVideoRenderer::Copy(
scoped_refptr<VideoFrame> video_frame,
cc::PaintCanvas* canvas,
viz::RasterContextProvider* raster_context_provider) { … }
namespace {
scoped_refptr<VideoFrame> DownShiftHighbitVideoFrame(
const VideoFrame* video_frame) { … }
void FlipAndConvertY16(const VideoFrame* video_frame,
uint8_t* out,
unsigned format,
unsigned type,
bool flip_y,
size_t output_row_bytes) { … }
bool TexImageHelper(VideoFrame* frame,
unsigned format,
unsigned type,
bool flip_y,
scoped_refptr<DataBuffer>* temp_buffer) { … }
void TextureSubImageUsingIntermediate(unsigned target,
unsigned texture,
gpu::gles2::GLES2Interface* gl,
VideoFrame* frame,
int temp_internalformat,
unsigned temp_format,
unsigned temp_type,
int level,
int xoffset,
int yoffset,
bool flip_y,
bool premultiply_alpha) { … }
}
void PaintCanvasVideoRenderer::ConvertVideoFrameToRGBPixels(
const VideoFrame* video_frame,
void* rgb_pixels,
size_t row_bytes,
bool premultiply_alpha,
FilterMode filter,
bool disable_threading) { … }
viz::SharedImageFormat PaintCanvasVideoRenderer::GetRGBPixelsOutputFormat() { … }
bool PaintCanvasVideoRenderer::CopyVideoFrameTexturesToGLTexture(
viz::RasterContextProvider* raster_context_provider,
gpu::gles2::GLES2Interface* destination_gl,
const gpu::Capabilities& destination_gl_capabilities,
scoped_refptr<VideoFrame> video_frame,
unsigned int target,
unsigned int texture,
unsigned int internal_format,
unsigned int format,
unsigned int type,
int level,
bool premultiply_alpha,
bool flip_y) { … }
#if !BUILDFLAG(IS_ANDROID)
bool PaintCanvasVideoRenderer::UploadVideoFrameToGLTexture(
viz::RasterContextProvider* raster_context_provider,
gpu::gles2::GLES2Interface* destination_gl,
const gpu::Capabilities& destination_gl_capabilities,
scoped_refptr<VideoFrame> video_frame,
unsigned int target,
unsigned int texture,
unsigned int internal_format,
unsigned int format,
unsigned int type,
bool flip_y) { … }
#endif
bool PaintCanvasVideoRenderer::CopyVideoFrameYUVDataToGLTexture(
viz::RasterContextProvider* raster_context_provider,
gpu::gles2::GLES2Interface* destination_gl,
const gpu::Capabilities& destination_gl_capabilities,
scoped_refptr<VideoFrame> video_frame,
unsigned int target,
unsigned int texture,
unsigned int internal_format,
unsigned int format,
unsigned int type,
int level,
bool premultiply_alpha,
bool flip_y) { … }
bool PaintCanvasVideoRenderer::TexImage2D(
unsigned target,
unsigned texture,
gpu::gles2::GLES2Interface* gl,
const gpu::Capabilities& gpu_capabilities,
VideoFrame* frame,
int level,
int internalformat,
unsigned format,
unsigned type,
bool flip_y,
bool premultiply_alpha) { … }
bool PaintCanvasVideoRenderer::TexSubImage2D(unsigned target,
gpu::gles2::GLES2Interface* gl,
VideoFrame* frame,
int level,
unsigned format,
unsigned type,
int xoffset,
int yoffset,
bool flip_y,
bool premultiply_alpha) { … }
void PaintCanvasVideoRenderer::ResetCache() { … }
PaintCanvasVideoRenderer::Cache::Cache(VideoFrame::ID frame_id)
: … { … }
PaintCanvasVideoRenderer::Cache::~Cache() = default;
bool PaintCanvasVideoRenderer::Cache::Recycle() { … }
bool PaintCanvasVideoRenderer::UpdateLastImage(
scoped_refptr<VideoFrame> video_frame,
viz::RasterContextProvider* raster_context_provider,
bool allow_wrap_texture) { … }
bool PaintCanvasVideoRenderer::CanUseCopyVideoFrameToSharedImage(
const VideoFrame& video_frame) { … }
gpu::SyncToken PaintCanvasVideoRenderer::CopyVideoFrameToSharedImage(
viz::RasterContextProvider* raster_context_provider,
scoped_refptr<VideoFrame> video_frame,
const gpu::MailboxHolder& destination,
bool use_visible_rect) { … }
PaintCanvasVideoRenderer::YUVTextureCache::YUVTextureCache() = default;
PaintCanvasVideoRenderer::YUVTextureCache::~YUVTextureCache() { … }
void PaintCanvasVideoRenderer::YUVTextureCache::Reset() { … }
gfx::Size PaintCanvasVideoRenderer::LastImageDimensionsForTesting() { … }
bool PaintCanvasVideoRenderer::CacheBackingWrapsTexture() const { … }
}