bool SharedSurface_IOSurface::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) { // Calling glReadPixels when an IOSurface is bound to the current framebuffer // can cause corruption in following glReadPixel calls (even if they aren't // reading from an IOSurface). // We workaround this by copying to a temporary texture, and doing the readback // from that. MOZ_ASSERT(mGL->IsCurrent()); ScopedTexture destTex(mGL); { ScopedFramebufferForTexture srcFB(mGL, ProdTexture(), ProdTextureTarget()); ScopedBindFramebuffer bindFB(mGL, srcFB.FB()); ScopedBindTexture bindTex(mGL, destTex.Texture()); mGL->raw_fCopyTexImage2D(LOCAL_GL_TEXTURE_2D, 0, mHasAlpha ? LOCAL_GL_RGBA : LOCAL_GL_RGB, x, y, width, height, 0); } ScopedFramebufferForTexture destFB(mGL, destTex.Texture()); ScopedBindFramebuffer bindFB(mGL, destFB.FB()); mGL->raw_fReadPixels(0, 0, width, height, format, type, pixels); return true; }
bool GLLibraryEGL::ReadbackEGLImage(EGLImage image, gfx::DataSourceSurface* out_surface) { StaticMutexAutoUnlock lock(sMutex); if (!mReadbackGL) { nsCString discardFailureId; mReadbackGL = gl::GLContextProvider::CreateHeadless(gl::CreateContextFlags::NONE, &discardFailureId); } ScopedTexture destTex(mReadbackGL); const GLuint target = mReadbackGL->GetPreferredEGLImageTextureTarget(); ScopedBindTexture autoTex(mReadbackGL, destTex.Texture(), target); mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST); mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST); mReadbackGL->fEGLImageTargetTexture2D(target, image); ShaderConfigOGL config = ShaderConfigFromTargetAndFormat(target, out_surface->GetFormat()); int shaderConfig = config.mFeatures; mReadbackGL->ReadTexImageHelper()->ReadTexImage(out_surface, 0, target, out_surface->GetSize(), shaderConfig); return true; }
bool SharedSurface_IOSurface::CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { /* Bug 896693 - OpenGL framebuffers that are backed by IOSurface on OSX expose a bug * in glCopyTexImage2D --- internalformats GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA * return the wrong results. To work around, copy framebuffer to a temporary texture * using GL_RGBA (which works), attach as read framebuffer and glCopyTexImage2D * instead. */ // https://www.opengl.org/sdk/docs/man3/xhtml/glCopyTexImage2D.xml says that width or // height set to 0 results in a NULL texture. Lets not do any work and punt to // original glCopyTexImage2D, since the FBO below will fail when trying to attach a // texture of 0 width or height. if (width == 0 || height == 0) return false; switch (internalformat) { case LOCAL_GL_ALPHA: case LOCAL_GL_LUMINANCE: case LOCAL_GL_LUMINANCE_ALPHA: break; default: return false; } MOZ_ASSERT(mGL->IsCurrent()); ScopedTexture destTex(mGL); { ScopedBindTexture bindTex(mGL, destTex.Texture()); mGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST); mGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST); mGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); mGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); mGL->raw_fCopyTexImage2D(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, x, y, width, height, 0); } ScopedFramebufferForTexture tmpFB(mGL, destTex.Texture(), LOCAL_GL_TEXTURE_2D); ScopedBindFramebuffer bindFB(mGL, tmpFB.FB()); mGL->raw_fCopyTexImage2D(target, level, internalformat, x, y, width, height, border); return true; }