gecko-dev/gfx/gl/GLBlitHelper.h

339 строки
10 KiB
C++

/* -*- 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/. */
#ifndef GLBLITHELPER_H_
#define GLBLITHELPER_H_
#include <array>
#include <cstdint>
#include <map>
#include <memory>
#include <unordered_map>
#include "Colorspaces.h"
#include "GLConsts.h"
#include "GLContextTypes.h"
#include "GLTypes.h"
#include "nsSize.h"
#include "nsString.h"
#include "nsTString.h"
#include "mozilla/ipc/IPCTypes.h"
#include "mozilla/Attributes.h"
#include "mozilla/Maybe.h"
#include "mozilla/gfx/Point.h"
#include "mozilla/gfx/Rect.h"
#include "mozilla/gfx/Types.h"
#include <map>
#ifdef XP_WIN
# include <windows.h>
# include "mozilla/RefPtr.h"
# include "mozilla/ipc/IPCTypes.h"
struct ID3D11Device;
struct ID3D11Texture2D;
#endif
#ifdef XP_MACOSX
class MacIOSurface;
#endif
#ifdef MOZ_WIDGET_ANDROID
# include "mozilla/java/GeckoSurfaceTextureWrappers.h"
#endif
#ifdef MOZ_WAYLAND
class DMABufSurface;
#endif
namespace mozilla {
namespace layers {
class Image;
class GPUVideoImage;
struct PlanarYCbCrData;
class PlanarYCbCrImage;
class SurfaceDescriptor;
class SurfaceDescriptorBuffer;
#ifdef XP_WIN
class D3D11ShareHandleImage;
class D3D11TextureIMFSampleImage;
class D3D11YCbCrImage;
class SurfaceDescriptorD3D10;
class SurfaceDescriptorDXGIYCbCr;
#endif
#ifdef MOZ_WIDGET_ANDROID
class SurfaceTextureDescriptor;
#endif
#ifdef XP_MACOSX
class MacIOSurfaceImage;
#endif
#ifdef MOZ_WAYLAND
class DMABUFSurfaceImage;
#endif
} // namespace layers
namespace gl {
class BindAnglePlanes;
class GLBlitHelper;
class GLContext;
class Texture;
bool GuessDivisors(const gfx::IntSize& ySize, const gfx::IntSize& uvSize,
gfx::IntSize* const out_divisors);
template <uint8_t N>
struct Mat {
float m[N * N]; // column-major, for GL
float& at(const uint8_t x, const uint8_t y) { return m[N * x + y]; }
static Mat<N> I() {
auto ret = Mat<N>{};
for (uint8_t i = 0; i < N; i++) {
ret.at(i, i) = 1.0f;
}
return ret;
}
Mat<N> operator*(const Mat<N>& r) const {
Mat<N> ret;
for (uint8_t x = 0; x < N; x++) {
for (uint8_t y = 0; y < N; y++) {
float sum = 0.0f;
for (uint8_t i = 0; i < N; i++) {
sum += at(i, y) * r.at(x, i);
}
ret.at(x, y) = sum;
}
}
return ret;
}
};
typedef Mat<3> Mat3;
Mat3 SubRectMat3(float x, float y, float w, float h);
Mat3 SubRectMat3(const gfx::IntRect& subrect, const gfx::IntSize& size);
Mat3 SubRectMat3(const gfx::IntRect& bigSubrect, const gfx::IntSize& smallSize,
const gfx::IntSize& divisors);
class DrawBlitProg final {
const GLBlitHelper& mParent;
const GLuint mProg;
const GLint mLoc_uDestMatrix;
const GLint mLoc_uTexMatrix0;
const GLint mLoc_uTexMatrix1;
const GLint mLoc_uColorLut;
const GLint mLoc_uColorMatrix;
GLenum mType_uColorMatrix = 0;
public:
struct Key final {
const char* fragHeader = nullptr;
std::array<const char*, 4> fragParts = {};
auto Members() const { return std::tie(fragHeader, fragParts); }
friend bool operator<(const Key& a, const Key& b) {
return a.Members() < b.Members();
}
};
DrawBlitProg(const GLBlitHelper* parent, GLuint prog);
~DrawBlitProg();
struct BaseArgs final {
Mat3 texMatrix0;
bool yFlip;
gfx::IntSize
destSize; // Always needed for (at least) setting the viewport.
Maybe<gfx::IntRect> destRect;
Maybe<uint32_t> texUnitForColorLut;
};
struct YUVArgs final {
Mat3 texMatrix1;
Maybe<gfx::YUVColorSpace> colorSpaceForMatrix;
};
void Draw(const BaseArgs& args, const YUVArgs* argsYUV = nullptr) const;
};
class ScopedSaveMultiTex final {
GLContext& mGL;
const std::vector<uint8_t> mTexUnits;
const GLenum mTexTarget;
const GLuint mOldTexUnit;
GLuint mOldTexSampler[3];
GLuint mOldTex[3];
public:
ScopedSaveMultiTex(GLContext* gl, const std::vector<uint8_t>& texUnits,
GLenum texTarget);
~ScopedSaveMultiTex();
};
/** Buffer blitting helper */
class GLBlitHelper final {
friend class BindAnglePlanes;
friend class DrawBlitProg;
friend class GLContext;
GLContext* const mGL;
mutable std::map<DrawBlitProg::Key, const DrawBlitProg*> mDrawBlitProgs;
GLuint mQuadVAO = 0;
GLuint mQuadVBO = 0;
nsCString mDrawBlitProg_VersionLine;
const GLuint mDrawBlitProg_VertShader;
GLuint mYuvUploads[3] = {};
gfx::IntSize mYuvUploads_YSize = {0, 0};
gfx::IntSize mYuvUploads_UVSize = {0, 0};
public:
struct ColorLutKey {
color::ColorspaceDesc src;
color::ColorspaceDesc dst;
auto Members() const { return std::tie(src, dst); }
INLINE_AUTO_MAPPABLE(ColorLutKey)
};
private:
mutable std::unordered_map<ColorLutKey, std::weak_ptr<gl::Texture>,
ColorLutKey::Hasher>
mColorLutTexMap;
public:
std::shared_ptr<gl::Texture> GetColorLutTex(const ColorLutKey& key) const;
#ifdef XP_WIN
mutable RefPtr<ID3D11Device> mD3D11;
ID3D11Device* GetD3D11() const;
#endif
const DrawBlitProg* GetDrawBlitProg(const DrawBlitProg::Key& key) const;
private:
const DrawBlitProg* CreateDrawBlitProg(const DrawBlitProg::Key& key) const;
public:
bool BlitPlanarYCbCr(const layers::PlanarYCbCrData&,
const gfx::IntSize& destSize, OriginPos destOrigin);
#ifdef MOZ_WIDGET_ANDROID
bool Blit(const java::GeckoSurfaceTexture::Ref& surfaceTexture,
const gfx::IntSize& destSize, const OriginPos destOrigin) const;
#endif
#ifdef XP_MACOSX
bool BlitImage(layers::MacIOSurfaceImage* srcImage,
const gfx::IntSize& destSize, OriginPos destOrigin) const;
#endif
#ifdef MOZ_WAYLAND
bool Blit(DMABufSurface* surface, const gfx::IntSize& destSize,
OriginPos destOrigin) const;
bool BlitImage(layers::DMABUFSurfaceImage* srcImage,
const gfx::IntSize& destSize, OriginPos destOrigin) const;
#endif
explicit GLBlitHelper(GLContext* gl);
public:
~GLBlitHelper();
void BlitFramebuffer(const gfx::IntRect& srcRect,
const gfx::IntRect& destRect,
GLuint filter = LOCAL_GL_NEAREST) const;
void BlitFramebufferToFramebuffer(GLuint srcFB, GLuint destFB,
const gfx::IntRect& srcRect,
const gfx::IntRect& destRect,
GLuint filter = LOCAL_GL_NEAREST) const;
void BlitFramebufferToTexture(GLuint destTex, const gfx::IntSize& srcSize,
const gfx::IntSize& destSize,
GLenum destTarget = LOCAL_GL_TEXTURE_2D) const;
void BlitTextureToFramebuffer(GLuint srcTex, const gfx::IntSize& srcSize,
const gfx::IntSize& destSize,
GLenum srcTarget = LOCAL_GL_TEXTURE_2D) const;
void BlitTextureToTexture(GLuint srcTex, GLuint destTex,
const gfx::IntSize& srcSize,
const gfx::IntSize& destSize,
GLenum srcTarget = LOCAL_GL_TEXTURE_2D,
GLenum destTarget = LOCAL_GL_TEXTURE_2D) const;
void DrawBlitTextureToFramebuffer(GLuint srcTex, const gfx::IntSize& srcSize,
const gfx::IntSize& destSize,
GLenum srcTarget = LOCAL_GL_TEXTURE_2D,
bool srcIsBGRA = false) const;
bool BlitImageToFramebuffer(layers::Image* srcImage,
const gfx::IntSize& destSize,
OriginPos destOrigin);
bool BlitSdToFramebuffer(const layers::SurfaceDescriptor&,
const gfx::IntSize& destSize, OriginPos destOrigin);
private:
bool BlitImage(layers::GPUVideoImage* srcImage, const gfx::IntSize& destSize,
OriginPos destOrigin) const;
#ifdef XP_MACOSX
bool BlitImage(MacIOSurface* const iosurf, const gfx::IntSize& destSize,
OriginPos destOrigin) const;
#endif
#ifdef XP_WIN
// GLBlitHelperD3D.cpp:
bool BlitImage(layers::D3D11ShareHandleImage* srcImage,
const gfx::IntSize& destSize, OriginPos destOrigin) const;
bool BlitImage(layers::D3D11TextureIMFSampleImage* srcImage,
const gfx::IntSize& destSize, OriginPos destOrigin) const;
bool BlitImage(layers::D3D11YCbCrImage* srcImage,
const gfx::IntSize& destSize, OriginPos destOrigin) const;
bool BlitDescriptor(const layers::SurfaceDescriptorD3D10& desc,
const gfx::IntSize& destSize, OriginPos destOrigin) const;
bool BlitDescriptor(const layers::SurfaceDescriptorDXGIYCbCr& desc,
const gfx::IntSize& destSize,
const OriginPos destOrigin) const;
bool BlitAngleYCbCr(const WindowsHandle (&handleList)[3],
const gfx::IntRect& clipRect, const gfx::IntSize& ySize,
const gfx::IntSize& uvSize,
const gfx::YUVColorSpace colorSpace,
const gfx::IntSize& destSize, OriginPos destOrigin) const;
bool BlitAnglePlanes(uint8_t numPlanes,
const RefPtr<ID3D11Texture2D>* texD3DList,
const DrawBlitProg* prog,
const DrawBlitProg::BaseArgs& baseArgs,
const DrawBlitProg::YUVArgs* const yuvArgs) const;
#endif
};
// -
// For DrawBlitProg::Key::fragParts
extern const char* const kFragHeader_Tex2D;
extern const char* const kFragHeader_Tex2DRect;
extern const char* const kFragHeader_TexExt;
extern const char* const kFragSample_OnePlane;
extern const char* const kFragSample_TwoPlane;
extern const char* const kFragSample_ThreePlane;
extern const char* const kFragConvert_None;
extern const char* const kFragConvert_BGR;
extern const char* const kFragConvert_ColorMatrix;
extern const char* const kFragConvert_ColorLut;
extern const char* const kFragMixin_AlphaMultColors;
extern const char* const kFragMixin_AlphaClampColors;
extern const char* const kFragMixin_AlphaOne;
} // namespace gl
} // namespace mozilla
#endif // GLBLITHELPER_H_