|
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 "mozilla/Preferences.h" |
|
7 |
|
8 #include "SharedSurfaceGralloc.h" |
|
9 |
|
10 #include "GLContext.h" |
|
11 #include "SharedSurfaceGL.h" |
|
12 #include "SurfaceFactory.h" |
|
13 #include "GLLibraryEGL.h" |
|
14 #include "mozilla/layers/GrallocTextureClient.h" |
|
15 #include "mozilla/layers/ShadowLayers.h" |
|
16 |
|
17 #include "ui/GraphicBuffer.h" |
|
18 #include "../layers/ipc/ShadowLayers.h" |
|
19 #include "ScopedGLHelpers.h" |
|
20 |
|
21 #include "gfxPlatform.h" |
|
22 #include "gfx2DGlue.h" |
|
23 #include "gfxPrefs.h" |
|
24 |
|
25 #define DEBUG_GRALLOC |
|
26 #ifdef DEBUG_GRALLOC |
|
27 #define DEBUG_PRINT(...) do { printf_stderr(__VA_ARGS__); } while (0) |
|
28 #else |
|
29 #define DEBUG_PRINT(...) do { } while (0) |
|
30 #endif |
|
31 |
|
32 using namespace mozilla; |
|
33 using namespace mozilla::gfx; |
|
34 using namespace gl; |
|
35 using namespace layers; |
|
36 using namespace android; |
|
37 |
|
38 SurfaceFactory_Gralloc::SurfaceFactory_Gralloc(GLContext* prodGL, |
|
39 const SurfaceCaps& caps, |
|
40 layers::ISurfaceAllocator* allocator) |
|
41 : SurfaceFactory_GL(prodGL, SharedSurfaceType::Gralloc, caps) |
|
42 { |
|
43 if (caps.surfaceAllocator) { |
|
44 allocator = caps.surfaceAllocator; |
|
45 } |
|
46 |
|
47 MOZ_ASSERT(allocator); |
|
48 |
|
49 mAllocator = allocator; |
|
50 } |
|
51 |
|
52 SharedSurface_Gralloc* |
|
53 SharedSurface_Gralloc::Create(GLContext* prodGL, |
|
54 const GLFormats& formats, |
|
55 const gfx::IntSize& size, |
|
56 bool hasAlpha, |
|
57 ISurfaceAllocator* allocator) |
|
58 { |
|
59 GLLibraryEGL* egl = &sEGLLibrary; |
|
60 MOZ_ASSERT(egl); |
|
61 |
|
62 DEBUG_PRINT("SharedSurface_Gralloc::Create -------\n"); |
|
63 |
|
64 if (!HasExtensions(egl, prodGL)) |
|
65 return nullptr; |
|
66 |
|
67 gfxContentType type = hasAlpha ? gfxContentType::COLOR_ALPHA |
|
68 : gfxContentType::COLOR; |
|
69 |
|
70 gfxImageFormat format |
|
71 = gfxPlatform::GetPlatform()->OptimalFormatForContent(type); |
|
72 |
|
73 RefPtr<GrallocTextureClientOGL> grallocTC = |
|
74 new GrallocTextureClientOGL( |
|
75 allocator, |
|
76 gfx::ImageFormatToSurfaceFormat(format), |
|
77 gfx::BackendType::NONE, // we don't need to use it with a DrawTarget |
|
78 TEXTURE_FLAGS_DEFAULT); |
|
79 |
|
80 if (!grallocTC->AllocateForGLRendering(size)) { |
|
81 return nullptr; |
|
82 } |
|
83 |
|
84 sp<GraphicBuffer> buffer = grallocTC->GetGraphicBuffer(); |
|
85 |
|
86 EGLDisplay display = egl->Display(); |
|
87 EGLClientBuffer clientBuffer = buffer->getNativeBuffer(); |
|
88 EGLint attrs[] = { |
|
89 LOCAL_EGL_NONE, LOCAL_EGL_NONE |
|
90 }; |
|
91 EGLImage image = egl->fCreateImage(display, |
|
92 EGL_NO_CONTEXT, |
|
93 LOCAL_EGL_NATIVE_BUFFER_ANDROID, |
|
94 clientBuffer, attrs); |
|
95 if (!image) { |
|
96 return nullptr; |
|
97 } |
|
98 |
|
99 prodGL->MakeCurrent(); |
|
100 GLuint prodTex = 0; |
|
101 prodGL->fGenTextures(1, &prodTex); |
|
102 ScopedBindTexture autoTex(prodGL, prodTex); |
|
103 |
|
104 prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR); |
|
105 prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR); |
|
106 prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); |
|
107 prodGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); |
|
108 |
|
109 prodGL->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, image); |
|
110 |
|
111 egl->fDestroyImage(display, image); |
|
112 |
|
113 SharedSurface_Gralloc *surf = new SharedSurface_Gralloc(prodGL, size, hasAlpha, egl, allocator, grallocTC, prodTex); |
|
114 |
|
115 DEBUG_PRINT("SharedSurface_Gralloc::Create: success -- surface %p, GraphicBuffer %p.\n", surf, buffer.get()); |
|
116 |
|
117 return surf; |
|
118 } |
|
119 |
|
120 |
|
121 bool |
|
122 SharedSurface_Gralloc::HasExtensions(GLLibraryEGL* egl, GLContext* gl) |
|
123 { |
|
124 return egl->HasKHRImageBase() && |
|
125 gl->IsExtensionSupported(GLContext::OES_EGL_image); |
|
126 } |
|
127 |
|
128 SharedSurface_Gralloc::~SharedSurface_Gralloc() |
|
129 { |
|
130 |
|
131 DEBUG_PRINT("[SharedSurface_Gralloc %p] destroyed\n", this); |
|
132 |
|
133 mGL->MakeCurrent(); |
|
134 mGL->fDeleteTextures(1, &mProdTex); |
|
135 } |
|
136 |
|
137 void |
|
138 SharedSurface_Gralloc::Fence() |
|
139 { |
|
140 // We should be able to rely on genlock write locks/read locks. |
|
141 // But they're broken on some configs, and even a glFinish doesn't |
|
142 // work. glReadPixels seems to, though. |
|
143 if (gfxPrefs::GrallocFenceWithReadPixels()) { |
|
144 mGL->MakeCurrent(); |
|
145 // read a 1x1 pixel |
|
146 unsigned char pixels[4]; |
|
147 mGL->fReadPixels(0, 0, 1, 1, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, &pixels[0]); |
|
148 } |
|
149 } |
|
150 |
|
151 bool |
|
152 SharedSurface_Gralloc::WaitSync() |
|
153 { |
|
154 return true; |
|
155 } |