michael@0: /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "SharedSurfaceIO.h" michael@0: #include "GLContextCGL.h" michael@0: #include "mozilla/gfx/MacIOSurface.h" michael@0: #include "mozilla/DebugOnly.h" michael@0: #include "ScopedGLHelpers.h" michael@0: michael@0: namespace mozilla { michael@0: namespace gl { michael@0: michael@0: using namespace gfx; michael@0: michael@0: /* static */ SharedSurface_IOSurface* michael@0: SharedSurface_IOSurface::Create(MacIOSurface* surface, GLContext *gl, bool hasAlpha) michael@0: { michael@0: MOZ_ASSERT(surface); michael@0: MOZ_ASSERT(gl); michael@0: michael@0: gfx::IntSize size(surface->GetWidth(), surface->GetHeight()); michael@0: return new SharedSurface_IOSurface(surface, gl, size, hasAlpha); michael@0: } michael@0: michael@0: void michael@0: SharedSurface_IOSurface::Fence() michael@0: { michael@0: mGL->MakeCurrent(); michael@0: mGL->fFlush(); michael@0: } michael@0: michael@0: bool michael@0: SharedSurface_IOSurface::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, michael@0: GLenum format, GLenum type, GLvoid *pixels) michael@0: { michael@0: // Calling glReadPixels when an IOSurface is bound to the current framebuffer michael@0: // can cause corruption in following glReadPixel calls (even if they aren't michael@0: // reading from an IOSurface). michael@0: // We workaround this by copying to a temporary texture, and doing the readback michael@0: // from that. michael@0: MOZ_ASSERT(mGL->IsCurrent()); michael@0: michael@0: michael@0: ScopedTexture destTex(mGL); michael@0: { michael@0: ScopedFramebufferForTexture srcFB(mGL, ProdTexture(), ProdTextureTarget()); michael@0: michael@0: ScopedBindFramebuffer bindFB(mGL, srcFB.FB()); michael@0: ScopedBindTexture bindTex(mGL, destTex.Texture()); michael@0: mGL->fCopyTexImage2D(LOCAL_GL_TEXTURE_2D, 0, michael@0: HasAlpha() ? LOCAL_GL_RGBA : LOCAL_GL_RGB, michael@0: x, y, michael@0: width, height, 0); michael@0: } michael@0: michael@0: ScopedFramebufferForTexture destFB(mGL, destTex.Texture()); michael@0: michael@0: ScopedBindFramebuffer bindFB(mGL, destFB.FB()); michael@0: mGL->fReadPixels(0, 0, width, height, format, type, pixels); michael@0: return true; michael@0: } michael@0: michael@0: static void michael@0: BackTextureWithIOSurf(GLContext* gl, GLuint tex, MacIOSurface* ioSurf) michael@0: { michael@0: MOZ_ASSERT(gl->IsCurrent()); michael@0: michael@0: ScopedBindTexture texture(gl, tex, LOCAL_GL_TEXTURE_RECTANGLE_ARB); michael@0: michael@0: gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, michael@0: LOCAL_GL_TEXTURE_MIN_FILTER, michael@0: LOCAL_GL_LINEAR); michael@0: gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, michael@0: LOCAL_GL_TEXTURE_MAG_FILTER, michael@0: LOCAL_GL_LINEAR); michael@0: gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, michael@0: LOCAL_GL_TEXTURE_WRAP_S, michael@0: LOCAL_GL_CLAMP_TO_EDGE); michael@0: gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, michael@0: LOCAL_GL_TEXTURE_WRAP_T, michael@0: LOCAL_GL_CLAMP_TO_EDGE); michael@0: michael@0: CGLContextObj cgl = GLContextCGL::Cast(gl)->GetCGLContext(); michael@0: MOZ_ASSERT(cgl); michael@0: michael@0: ioSurf->CGLTexImageIOSurface2D(cgl); michael@0: } michael@0: michael@0: SharedSurface_IOSurface::SharedSurface_IOSurface(MacIOSurface* surface, michael@0: GLContext* gl, michael@0: const gfx::IntSize& size, michael@0: bool hasAlpha) michael@0: : SharedSurface_GL(SharedSurfaceType::IOSurface, AttachmentType::GLTexture, gl, size, hasAlpha) michael@0: , mSurface(surface) michael@0: , mCurConsGL(nullptr) michael@0: , mConsTex(0) michael@0: { michael@0: gl->MakeCurrent(); michael@0: mProdTex = 0; michael@0: gl->fGenTextures(1, &mProdTex); michael@0: BackTextureWithIOSurf(gl, mProdTex, surface); michael@0: } michael@0: michael@0: GLuint michael@0: SharedSurface_IOSurface::ConsTexture(GLContext* consGL) michael@0: { michael@0: if (!mCurConsGL) { michael@0: mCurConsGL = consGL; michael@0: } michael@0: MOZ_ASSERT(consGL == mCurConsGL); michael@0: michael@0: if (!mConsTex) { michael@0: consGL->MakeCurrent(); michael@0: mConsTex = 0; michael@0: consGL->fGenTextures(1, &mConsTex); michael@0: BackTextureWithIOSurf(consGL, mConsTex, mSurface); michael@0: } michael@0: michael@0: return mConsTex; michael@0: } michael@0: michael@0: SharedSurface_IOSurface::~SharedSurface_IOSurface() michael@0: { michael@0: if (mProdTex) { michael@0: DebugOnly success = mGL->MakeCurrent(); michael@0: MOZ_ASSERT(success); michael@0: mGL->fDeleteTextures(1, &mProdTex); michael@0: mGL->fDeleteTextures(1, &mConsTex); // This will work if we're shared. michael@0: } michael@0: } michael@0: michael@0: SharedSurface* michael@0: SurfaceFactory_IOSurface::CreateShared(const gfx::IntSize& size) michael@0: { michael@0: bool hasAlpha = mReadCaps.alpha; michael@0: RefPtr surf = michael@0: MacIOSurface::CreateIOSurface(size.width, size.height, 1.0, hasAlpha); michael@0: michael@0: if (!surf) { michael@0: NS_WARNING("Failed to create MacIOSurface."); michael@0: return nullptr; michael@0: } michael@0: michael@0: return SharedSurface_IOSurface::Create(surf, mGL, hasAlpha); michael@0: } michael@0: michael@0: } michael@0: }