mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 728524 - Render to shared EGLImage/Texture implementation. r=bgirard,vlad,jgilbert
This commit is contained in:
parent
ee5b6a2485
commit
5ec3a2efeb
@ -258,6 +258,7 @@ public:
|
||||
, mIsPBuffer(false)
|
||||
, mIsDoubleBuffered(false)
|
||||
, mCanBindToTexture(false)
|
||||
, mShareWithEGLImage(false)
|
||||
{
|
||||
// any EGL contexts will always be GLESv2
|
||||
SetIsGLES2(true);
|
||||
@ -327,6 +328,10 @@ public:
|
||||
PR_STATIC_ASSERT(sizeof(GLint) >= sizeof(int32_t));
|
||||
mMaxTextureImageSize = PR_INT32_MAX;
|
||||
|
||||
mShareWithEGLImage = sEGLLibrary.HasKHRImageBase() &&
|
||||
sEGLLibrary.HasKHRImageTexture2D() &&
|
||||
IsExtensionSupported(OES_EGL_image);
|
||||
|
||||
if (ok)
|
||||
InitFramebuffers();
|
||||
|
||||
@ -584,6 +589,13 @@ public:
|
||||
return sEGLLibrary.HasKHRLockSurface();
|
||||
}
|
||||
|
||||
virtual SharedTextureHandle CreateSharedHandle(TextureImage::TextureShareType aType);
|
||||
virtual void UpdateSharedHandle(TextureImage::TextureShareType aType,
|
||||
SharedTextureHandle aSharedHandle);
|
||||
virtual void ReleaseSharedHandle(TextureImage::TextureShareType aType,
|
||||
SharedTextureHandle aSharedHandle);
|
||||
virtual bool AttachSharedHandle(TextureImage::TextureShareType aType,
|
||||
SharedTextureHandle aSharedHandle);
|
||||
protected:
|
||||
friend class GLContextProviderEGL;
|
||||
|
||||
@ -597,6 +609,7 @@ protected:
|
||||
bool mIsPBuffer;
|
||||
bool mIsDoubleBuffered;
|
||||
bool mCanBindToTexture;
|
||||
bool mShareWithEGLImage;
|
||||
|
||||
static EGLSurface CreatePBufferSurfaceTryingPowerOfTwo(EGLConfig config,
|
||||
EGLenum bindToTextureFormat,
|
||||
@ -642,6 +655,161 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
class EGLTextureWrapper
|
||||
{
|
||||
public:
|
||||
EGLTextureWrapper(GLContext* aContext, GLuint aTexture)
|
||||
: mContext(aContext)
|
||||
, mTexture(aTexture)
|
||||
, mEGLImage(nsnull)
|
||||
{
|
||||
}
|
||||
|
||||
bool CreateEGLImage() {
|
||||
MOZ_ASSERT(!mEGLImage && mTexture && sEGLLibrary.HasKHRImageBase());
|
||||
static const EGLint eglAttributes[] = {
|
||||
LOCAL_EGL_NONE
|
||||
};
|
||||
GLContextEGL* ctx = static_cast<GLContextEGL*>(mContext.get());
|
||||
mEGLImage = sEGLLibrary.fCreateImage(EGL_DISPLAY(), ctx->Context(), LOCAL_EGL_GL_TEXTURE_2D,
|
||||
(EGLClientBuffer)mTexture, eglAttributes);
|
||||
if (!mEGLImage) {
|
||||
#ifdef DEBUG
|
||||
printf_stderr("Could not create EGL images: ERROR (0x%04x)\n", sEGLLibrary.fGetError());
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual ~EGLTextureWrapper() {
|
||||
if (mEGLImage) {
|
||||
sEGLLibrary.fDestroyImage(EGL_DISPLAY(), mEGLImage);
|
||||
mEGLImage = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
GLuint GetTextureID() {
|
||||
return mTexture;
|
||||
}
|
||||
|
||||
GLContext* GetContext() {
|
||||
return mContext.get();
|
||||
}
|
||||
|
||||
const EGLImage GetEGLImage() {
|
||||
return mEGLImage;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<GLContext> mContext;
|
||||
GLuint mTexture;
|
||||
EGLImage mEGLImage;
|
||||
};
|
||||
|
||||
void
|
||||
GLContextEGL::UpdateSharedHandle(TextureImage::TextureShareType aType,
|
||||
SharedTextureHandle aSharedHandle)
|
||||
{
|
||||
if (aType != TextureImage::ThreadShared) {
|
||||
NS_ERROR("Implementation not available for this sharing type");
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mShareWithEGLImage, "EGLImage not supported or disabled in runtime");
|
||||
|
||||
EGLTextureWrapper* wrap = (EGLTextureWrapper*)aSharedHandle;
|
||||
// We need to copy the current GLContext drawing buffer to the texture
|
||||
// exported by the EGLImage. Need to save both the read FBO and the texture
|
||||
// binding, because we're going to munge them to do this.
|
||||
GLuint prevRead = GetUserBoundReadFBO();
|
||||
GLint oldtex = -1;
|
||||
BindUserReadFBO(0);
|
||||
fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &oldtex);
|
||||
MOZ_ASSERT(oldtex != -1);
|
||||
fBindTexture(LOCAL_GL_TEXTURE_2D, wrap->GetTextureID());
|
||||
|
||||
// CopyTexSubImage2D, is ~2x slower than simple FBO render to texture with draw quads,
|
||||
// but render with draw quads require complex and hard to maintain context save/restore code
|
||||
fCopyTexSubImage2D(LOCAL_GL_TEXTURE_2D, 0, 0, 0,
|
||||
0, 0, mOffscreenActualSize.width,
|
||||
mOffscreenActualSize.height);
|
||||
|
||||
fBindTexture(LOCAL_GL_TEXTURE_2D, oldtex);
|
||||
BindUserReadFBO(prevRead);
|
||||
|
||||
// Make Shared Handle fully resolved in order to
|
||||
// guarantee content ready to draw in different thread GLContext
|
||||
GuaranteeResolve();
|
||||
}
|
||||
|
||||
SharedTextureHandle
|
||||
GLContextEGL::CreateSharedHandle(TextureImage::TextureShareType aType)
|
||||
{
|
||||
if (aType != TextureImage::ThreadShared)
|
||||
return nsnull;
|
||||
|
||||
if (!mShareWithEGLImage)
|
||||
return nsnull;
|
||||
|
||||
MakeCurrent();
|
||||
GLuint texture = 0;
|
||||
ContextFormat fmt = ActualFormat();
|
||||
CreateTextureForOffscreen(ChooseGLFormats(fmt), mOffscreenSize, texture);
|
||||
// texture ownership moved to EGLTextureWrapper after this point
|
||||
// and texture will be deleted in EGLTextureWrapper dtor
|
||||
EGLTextureWrapper* tex = new EGLTextureWrapper(this, texture);
|
||||
if (!tex->CreateEGLImage()) {
|
||||
NS_ERROR("EGLImage creation for EGLTextureWrapper failed");
|
||||
ReleaseSharedHandle(aType, (SharedTextureHandle)tex);
|
||||
|
||||
// Stop trying to create shared image Handle
|
||||
mShareWithEGLImage = false;
|
||||
return nsnull;
|
||||
}
|
||||
// Raw pointer shared across threads
|
||||
return (SharedTextureHandle)tex;
|
||||
}
|
||||
|
||||
void GLContextEGL::ReleaseSharedHandle(TextureImage::TextureShareType aType,
|
||||
SharedTextureHandle aSharedHandle)
|
||||
{
|
||||
if (aType != TextureImage::ThreadShared) {
|
||||
NS_ERROR("Implementation not available for this sharing type");
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mShareWithEGLImage, "EGLImage not supported or disabled in runtime");
|
||||
|
||||
EGLTextureWrapper* wrap = (EGLTextureWrapper*)aSharedHandle;
|
||||
GLContext *ctx = wrap->GetContext();
|
||||
if (ctx->IsDestroyed() || !ctx->IsOwningThreadCurrent()) {
|
||||
ctx = ctx->GetSharedContext();
|
||||
}
|
||||
// If we have a context, then we need to delete the texture;
|
||||
// if we don't have a context (either real or shared),
|
||||
// then they went away when the contex was deleted, because it
|
||||
// was the only one that had access to it.
|
||||
if (ctx && !ctx->IsDestroyed() && ctx->MakeCurrent()) {
|
||||
GLuint texture = wrap->GetTextureID();
|
||||
ctx->fDeleteTextures(1, &texture);
|
||||
}
|
||||
delete wrap;
|
||||
}
|
||||
|
||||
bool GLContextEGL::AttachSharedHandle(TextureImage::TextureShareType aType,
|
||||
SharedTextureHandle aSharedHandle)
|
||||
{
|
||||
if (aType != TextureImage::ThreadShared)
|
||||
return false;
|
||||
|
||||
NS_ASSERTION(mShareWithEGLImage, "EGLImage not supported or disabled in runtime");
|
||||
|
||||
EGLTextureWrapper* wrap = (EGLTextureWrapper*)aSharedHandle;
|
||||
sEGLLibrary.fImageTargetTexture2DOES(LOCAL_GL_TEXTURE_2D, wrap->GetEGLImage());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GLContextEGL::BindTex2DOffscreen(GLContext *aOffscreen)
|
||||
{
|
||||
|
@ -3253,6 +3253,9 @@ typedef void* GLeglImage;
|
||||
#define LOCAL_EGL_DRAW 0x3059
|
||||
#define LOCAL_EGL_CONTEXT_LOST 0x300E
|
||||
|
||||
// EGL_KHR_gl_texture_2D_image
|
||||
#define LOCAL_EGL_GL_TEXTURE_2D 0x30B1
|
||||
|
||||
// EGL_KHR_fence_sync
|
||||
#define LOCAL_EGL_SYNC_FENCE 0x30F9
|
||||
#define LOCAL_EGL_SYNC_TYPE 0x30F7
|
||||
|
Loading…
Reference in New Issue
Block a user