|
1 /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "SharedSurfaceIO.h" |
|
7 #include "GLContextCGL.h" |
|
8 #include "mozilla/gfx/MacIOSurface.h" |
|
9 #include "mozilla/DebugOnly.h" |
|
10 #include "ScopedGLHelpers.h" |
|
11 |
|
12 namespace mozilla { |
|
13 namespace gl { |
|
14 |
|
15 using namespace gfx; |
|
16 |
|
17 /* static */ SharedSurface_IOSurface* |
|
18 SharedSurface_IOSurface::Create(MacIOSurface* surface, GLContext *gl, bool hasAlpha) |
|
19 { |
|
20 MOZ_ASSERT(surface); |
|
21 MOZ_ASSERT(gl); |
|
22 |
|
23 gfx::IntSize size(surface->GetWidth(), surface->GetHeight()); |
|
24 return new SharedSurface_IOSurface(surface, gl, size, hasAlpha); |
|
25 } |
|
26 |
|
27 void |
|
28 SharedSurface_IOSurface::Fence() |
|
29 { |
|
30 mGL->MakeCurrent(); |
|
31 mGL->fFlush(); |
|
32 } |
|
33 |
|
34 bool |
|
35 SharedSurface_IOSurface::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, |
|
36 GLenum format, GLenum type, GLvoid *pixels) |
|
37 { |
|
38 // Calling glReadPixels when an IOSurface is bound to the current framebuffer |
|
39 // can cause corruption in following glReadPixel calls (even if they aren't |
|
40 // reading from an IOSurface). |
|
41 // We workaround this by copying to a temporary texture, and doing the readback |
|
42 // from that. |
|
43 MOZ_ASSERT(mGL->IsCurrent()); |
|
44 |
|
45 |
|
46 ScopedTexture destTex(mGL); |
|
47 { |
|
48 ScopedFramebufferForTexture srcFB(mGL, ProdTexture(), ProdTextureTarget()); |
|
49 |
|
50 ScopedBindFramebuffer bindFB(mGL, srcFB.FB()); |
|
51 ScopedBindTexture bindTex(mGL, destTex.Texture()); |
|
52 mGL->fCopyTexImage2D(LOCAL_GL_TEXTURE_2D, 0, |
|
53 HasAlpha() ? LOCAL_GL_RGBA : LOCAL_GL_RGB, |
|
54 x, y, |
|
55 width, height, 0); |
|
56 } |
|
57 |
|
58 ScopedFramebufferForTexture destFB(mGL, destTex.Texture()); |
|
59 |
|
60 ScopedBindFramebuffer bindFB(mGL, destFB.FB()); |
|
61 mGL->fReadPixels(0, 0, width, height, format, type, pixels); |
|
62 return true; |
|
63 } |
|
64 |
|
65 static void |
|
66 BackTextureWithIOSurf(GLContext* gl, GLuint tex, MacIOSurface* ioSurf) |
|
67 { |
|
68 MOZ_ASSERT(gl->IsCurrent()); |
|
69 |
|
70 ScopedBindTexture texture(gl, tex, LOCAL_GL_TEXTURE_RECTANGLE_ARB); |
|
71 |
|
72 gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, |
|
73 LOCAL_GL_TEXTURE_MIN_FILTER, |
|
74 LOCAL_GL_LINEAR); |
|
75 gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, |
|
76 LOCAL_GL_TEXTURE_MAG_FILTER, |
|
77 LOCAL_GL_LINEAR); |
|
78 gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, |
|
79 LOCAL_GL_TEXTURE_WRAP_S, |
|
80 LOCAL_GL_CLAMP_TO_EDGE); |
|
81 gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, |
|
82 LOCAL_GL_TEXTURE_WRAP_T, |
|
83 LOCAL_GL_CLAMP_TO_EDGE); |
|
84 |
|
85 CGLContextObj cgl = GLContextCGL::Cast(gl)->GetCGLContext(); |
|
86 MOZ_ASSERT(cgl); |
|
87 |
|
88 ioSurf->CGLTexImageIOSurface2D(cgl); |
|
89 } |
|
90 |
|
91 SharedSurface_IOSurface::SharedSurface_IOSurface(MacIOSurface* surface, |
|
92 GLContext* gl, |
|
93 const gfx::IntSize& size, |
|
94 bool hasAlpha) |
|
95 : SharedSurface_GL(SharedSurfaceType::IOSurface, AttachmentType::GLTexture, gl, size, hasAlpha) |
|
96 , mSurface(surface) |
|
97 , mCurConsGL(nullptr) |
|
98 , mConsTex(0) |
|
99 { |
|
100 gl->MakeCurrent(); |
|
101 mProdTex = 0; |
|
102 gl->fGenTextures(1, &mProdTex); |
|
103 BackTextureWithIOSurf(gl, mProdTex, surface); |
|
104 } |
|
105 |
|
106 GLuint |
|
107 SharedSurface_IOSurface::ConsTexture(GLContext* consGL) |
|
108 { |
|
109 if (!mCurConsGL) { |
|
110 mCurConsGL = consGL; |
|
111 } |
|
112 MOZ_ASSERT(consGL == mCurConsGL); |
|
113 |
|
114 if (!mConsTex) { |
|
115 consGL->MakeCurrent(); |
|
116 mConsTex = 0; |
|
117 consGL->fGenTextures(1, &mConsTex); |
|
118 BackTextureWithIOSurf(consGL, mConsTex, mSurface); |
|
119 } |
|
120 |
|
121 return mConsTex; |
|
122 } |
|
123 |
|
124 SharedSurface_IOSurface::~SharedSurface_IOSurface() |
|
125 { |
|
126 if (mProdTex) { |
|
127 DebugOnly<bool> success = mGL->MakeCurrent(); |
|
128 MOZ_ASSERT(success); |
|
129 mGL->fDeleteTextures(1, &mProdTex); |
|
130 mGL->fDeleteTextures(1, &mConsTex); // This will work if we're shared. |
|
131 } |
|
132 } |
|
133 |
|
134 SharedSurface* |
|
135 SurfaceFactory_IOSurface::CreateShared(const gfx::IntSize& size) |
|
136 { |
|
137 bool hasAlpha = mReadCaps.alpha; |
|
138 RefPtr<MacIOSurface> surf = |
|
139 MacIOSurface::CreateIOSurface(size.width, size.height, 1.0, hasAlpha); |
|
140 |
|
141 if (!surf) { |
|
142 NS_WARNING("Failed to create MacIOSurface."); |
|
143 return nullptr; |
|
144 } |
|
145 |
|
146 return SharedSurface_IOSurface::Create(surf, mGL, hasAlpha); |
|
147 } |
|
148 |
|
149 } |
|
150 } |