OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "gpu/command_buffer/service/texture_definition.h" | 5 #include "gpu/command_buffer/service/texture_definition.h" |
6 | 6 |
7 #include <list> | 7 #include <list> |
8 | 8 |
9 #include "base/memory/linked_ptr.h" | 9 #include "base/memory/linked_ptr.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
11 #include "base/synchronization/lock.h" | 11 #include "base/synchronization/lock.h" |
12 #include "gpu/command_buffer/service/texture_manager.h" | 12 #include "gpu/command_buffer/service/texture_manager.h" |
13 #include "ui/gl/gl_image.h" | 13 #include "ui/gl/gl_image.h" |
14 #include "ui/gl/gl_implementation.h" | 14 #include "ui/gl/gl_implementation.h" |
15 #include "ui/gl/scoped_binders.h" | 15 #include "ui/gl/scoped_binders.h" |
16 | 16 |
17 #if !defined(OS_MACOSX) | 17 #if !defined(OS_MACOSX) |
18 #include "ui/gl/gl_fence_egl.h" | |
19 #include "ui/gl/gl_surface_egl.h" | 18 #include "ui/gl/gl_surface_egl.h" |
20 #endif | 19 #endif |
21 | 20 |
22 namespace gpu { | 21 namespace gpu { |
23 namespace gles2 { | 22 namespace gles2 { |
24 | 23 |
25 namespace { | 24 namespace { |
26 | 25 |
27 class GLImageSync : public gfx::GLImage { | 26 class GLImageSync : public gfx::GLImage { |
28 public: | 27 public: |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 | 80 |
82 void GLImageSync::ReleaseTexImage(unsigned target) { | 81 void GLImageSync::ReleaseTexImage(unsigned target) { |
83 NOTREACHED(); | 82 NOTREACHED(); |
84 } | 83 } |
85 | 84 |
86 bool GLImageSync::CopyTexImage(unsigned target) { | 85 bool GLImageSync::CopyTexImage(unsigned target) { |
87 return false; | 86 return false; |
88 } | 87 } |
89 | 88 |
90 void GLImageSync::WillUseTexImage() { | 89 void GLImageSync::WillUseTexImage() { |
91 if (buffer_.get()) | |
92 buffer_->WillRead(this); | |
93 } | 90 } |
94 | 91 |
95 void GLImageSync::DidUseTexImage() { | 92 void GLImageSync::DidUseTexImage() { |
96 if (buffer_.get()) | |
97 buffer_->DidRead(this); | |
98 } | 93 } |
99 | 94 |
100 void GLImageSync::WillModifyTexImage() { | 95 void GLImageSync::WillModifyTexImage() { |
101 if (buffer_.get()) | |
102 buffer_->WillWrite(this); | |
103 } | 96 } |
104 | 97 |
105 void GLImageSync::DidModifyTexImage() { | 98 void GLImageSync::DidModifyTexImage() { |
106 if (buffer_.get()) | |
107 buffer_->DidWrite(this); | |
108 } | 99 } |
109 | 100 |
110 bool GLImageSync::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, | 101 bool GLImageSync::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, |
111 int z_order, | 102 int z_order, |
112 gfx::OverlayTransform transform, | 103 gfx::OverlayTransform transform, |
113 const gfx::Rect& bounds_rect, | 104 const gfx::Rect& bounds_rect, |
114 const gfx::RectF& crop_rect) { | 105 const gfx::RectF& crop_rect) { |
115 NOTREACHED(); | 106 NOTREACHED(); |
116 return false; | 107 return false; |
117 } | 108 } |
118 | 109 |
119 #if !defined(OS_MACOSX) | 110 #if !defined(OS_MACOSX) |
120 class NativeImageBufferEGL : public NativeImageBuffer { | 111 class NativeImageBufferEGL : public NativeImageBuffer { |
121 public: | 112 public: |
122 static scoped_refptr<NativeImageBufferEGL> Create(GLuint texture_id); | 113 static scoped_refptr<NativeImageBufferEGL> Create(GLuint texture_id); |
123 | 114 |
124 private: | 115 private: |
125 NativeImageBufferEGL(EGLDisplay display, EGLImageKHR image); | 116 NativeImageBufferEGL(EGLDisplay display, EGLImageKHR image); |
126 virtual ~NativeImageBufferEGL(); | 117 virtual ~NativeImageBufferEGL(); |
127 virtual void AddClient(gfx::GLImage* client) override; | 118 virtual void AddClient(gfx::GLImage* client) override; |
128 virtual void RemoveClient(gfx::GLImage* client) override; | 119 virtual void RemoveClient(gfx::GLImage* client) override; |
129 virtual bool IsClient(gfx::GLImage* client) override; | 120 virtual bool IsClient(gfx::GLImage* client) override; |
130 virtual void BindToTexture(GLenum target) override; | 121 virtual void BindToTexture(GLenum target) override; |
131 virtual void WillRead(gfx::GLImage* client) override; | |
132 virtual void WillWrite(gfx::GLImage* client) override; | |
133 virtual void DidRead(gfx::GLImage* client) override; | |
134 virtual void DidWrite(gfx::GLImage* client) override; | |
135 | 122 |
136 EGLDisplay egl_display_; | 123 EGLDisplay egl_display_; |
137 EGLImageKHR egl_image_; | 124 EGLImageKHR egl_image_; |
138 | 125 |
139 base::Lock lock_; | 126 base::Lock lock_; |
140 | 127 |
141 struct ClientInfo { | 128 struct ClientInfo { |
142 ClientInfo(gfx::GLImage* client); | 129 ClientInfo(gfx::GLImage* client); |
143 ~ClientInfo(); | 130 ~ClientInfo(); |
144 | 131 |
145 gfx::GLImage* client; | 132 gfx::GLImage* client; |
146 bool needs_wait_before_read; | 133 bool needs_wait_before_read; |
147 linked_ptr<gfx::GLFence> read_fence; | |
148 }; | 134 }; |
149 std::list<ClientInfo> client_infos_; | 135 std::list<ClientInfo> client_infos_; |
150 scoped_ptr<gfx::GLFence> write_fence_; | |
151 gfx::GLImage* write_client_; | 136 gfx::GLImage* write_client_; |
152 | 137 |
153 DISALLOW_COPY_AND_ASSIGN(NativeImageBufferEGL); | 138 DISALLOW_COPY_AND_ASSIGN(NativeImageBufferEGL); |
154 }; | 139 }; |
155 | 140 |
156 scoped_refptr<NativeImageBufferEGL> NativeImageBufferEGL::Create( | 141 scoped_refptr<NativeImageBufferEGL> NativeImageBufferEGL::Create( |
157 GLuint texture_id) { | 142 GLuint texture_id) { |
158 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); | 143 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); |
159 EGLContext egl_context = eglGetCurrentContext(); | 144 EGLContext egl_context = eglGetCurrentContext(); |
160 | 145 |
161 DCHECK_NE(EGL_NO_CONTEXT, egl_context); | 146 DCHECK_NE(EGL_NO_CONTEXT, egl_context); |
162 DCHECK_NE(EGL_NO_DISPLAY, egl_display); | 147 DCHECK_NE(EGL_NO_DISPLAY, egl_display); |
163 DCHECK(glIsTexture(texture_id)); | 148 DCHECK(glIsTexture(texture_id)); |
164 | 149 |
165 DCHECK(gfx::g_driver_egl.ext.b_EGL_KHR_image_base && | 150 DCHECK(gfx::g_driver_egl.ext.b_EGL_KHR_image_base && |
166 gfx::g_driver_egl.ext.b_EGL_KHR_gl_texture_2D_image && | 151 gfx::g_driver_egl.ext.b_EGL_KHR_gl_texture_2D_image && |
167 gfx::g_driver_gl.ext.b_GL_OES_EGL_image && | 152 gfx::g_driver_gl.ext.b_GL_OES_EGL_image); |
168 gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync); | |
169 | 153 |
170 const EGLint egl_attrib_list[] = { | 154 const EGLint egl_attrib_list[] = { |
171 EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; | 155 EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; |
172 EGLClientBuffer egl_buffer = reinterpret_cast<EGLClientBuffer>(texture_id); | 156 EGLClientBuffer egl_buffer = reinterpret_cast<EGLClientBuffer>(texture_id); |
173 EGLenum egl_target = EGL_GL_TEXTURE_2D_KHR; // TODO | 157 EGLenum egl_target = EGL_GL_TEXTURE_2D_KHR; // TODO |
174 | 158 |
175 EGLImageKHR egl_image = eglCreateImageKHR( | 159 EGLImageKHR egl_image = eglCreateImageKHR( |
176 egl_display, egl_context, egl_target, egl_buffer, egl_attrib_list); | 160 egl_display, egl_context, egl_target, egl_buffer, egl_attrib_list); |
177 | 161 |
178 if (egl_image == EGL_NO_IMAGE_KHR) | 162 if (egl_image == EGL_NO_IMAGE_KHR) |
179 return NULL; | 163 return NULL; |
180 | 164 |
181 return new NativeImageBufferEGL(egl_display, egl_image); | 165 return new NativeImageBufferEGL(egl_display, egl_image); |
182 } | 166 } |
183 | 167 |
184 NativeImageBufferEGL::ClientInfo::ClientInfo(gfx::GLImage* client) | 168 NativeImageBufferEGL::ClientInfo::ClientInfo(gfx::GLImage* client) |
185 : client(client), needs_wait_before_read(true) {} | 169 : client(client), needs_wait_before_read(true) {} |
186 | 170 |
187 NativeImageBufferEGL::ClientInfo::~ClientInfo() {} | 171 NativeImageBufferEGL::ClientInfo::~ClientInfo() {} |
188 | 172 |
189 NativeImageBufferEGL::NativeImageBufferEGL(EGLDisplay display, | 173 NativeImageBufferEGL::NativeImageBufferEGL(EGLDisplay display, |
190 EGLImageKHR image) | 174 EGLImageKHR image) |
191 : NativeImageBuffer(), | 175 : NativeImageBuffer(), |
192 egl_display_(display), | 176 egl_display_(display), |
193 egl_image_(image), | 177 egl_image_(image), |
194 write_fence_(new gfx::GLFenceEGL(true)), | |
195 write_client_(NULL) { | 178 write_client_(NULL) { |
196 DCHECK(egl_display_ != EGL_NO_DISPLAY); | 179 DCHECK(egl_display_ != EGL_NO_DISPLAY); |
197 DCHECK(egl_image_ != EGL_NO_IMAGE_KHR); | 180 DCHECK(egl_image_ != EGL_NO_IMAGE_KHR); |
198 } | 181 } |
199 | 182 |
200 NativeImageBufferEGL::~NativeImageBufferEGL() { | 183 NativeImageBufferEGL::~NativeImageBufferEGL() { |
201 DCHECK(client_infos_.empty()); | 184 DCHECK(client_infos_.empty()); |
202 if (egl_image_ != EGL_NO_IMAGE_KHR) | 185 if (egl_image_ != EGL_NO_IMAGE_KHR) |
203 eglDestroyImageKHR(egl_display_, egl_image_); | 186 eglDestroyImageKHR(egl_display_, egl_image_); |
204 } | 187 } |
(...skipping 29 matching lines...) Expand all Loading... |
234 return false; | 217 return false; |
235 } | 218 } |
236 | 219 |
237 void NativeImageBufferEGL::BindToTexture(GLenum target) { | 220 void NativeImageBufferEGL::BindToTexture(GLenum target) { |
238 DCHECK(egl_image_ != EGL_NO_IMAGE_KHR); | 221 DCHECK(egl_image_ != EGL_NO_IMAGE_KHR); |
239 glEGLImageTargetTexture2DOES(target, egl_image_); | 222 glEGLImageTargetTexture2DOES(target, egl_image_); |
240 DCHECK_EQ(static_cast<EGLint>(EGL_SUCCESS), eglGetError()); | 223 DCHECK_EQ(static_cast<EGLint>(EGL_SUCCESS), eglGetError()); |
241 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | 224 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
242 } | 225 } |
243 | 226 |
244 void NativeImageBufferEGL::WillRead(gfx::GLImage* client) { | |
245 base::AutoLock lock(lock_); | |
246 if (!write_fence_.get() || write_client_ == client) | |
247 return; | |
248 | |
249 for (std::list<ClientInfo>::iterator it = client_infos_.begin(); | |
250 it != client_infos_.end(); | |
251 it++) { | |
252 if (it->client == client) { | |
253 if (it->needs_wait_before_read) { | |
254 it->needs_wait_before_read = false; | |
255 write_fence_->ServerWait(); | |
256 } | |
257 return; | |
258 } | |
259 } | |
260 NOTREACHED(); | |
261 } | |
262 | |
263 void NativeImageBufferEGL::WillWrite(gfx::GLImage* client) { | |
264 base::AutoLock lock(lock_); | |
265 if (write_client_ != client) | |
266 write_fence_->ServerWait(); | |
267 | |
268 for (std::list<ClientInfo>::iterator it = client_infos_.begin(); | |
269 it != client_infos_.end(); | |
270 it++) { | |
271 if (it->read_fence.get() && it->client != client) | |
272 it->read_fence->ServerWait(); | |
273 } | |
274 } | |
275 | |
276 void NativeImageBufferEGL::DidRead(gfx::GLImage* client) { | |
277 base::AutoLock lock(lock_); | |
278 for (std::list<ClientInfo>::iterator it = client_infos_.begin(); | |
279 it != client_infos_.end(); | |
280 it++) { | |
281 if (it->client == client) { | |
282 it->read_fence = make_linked_ptr(new gfx::GLFenceEGL(true)); | |
283 return; | |
284 } | |
285 } | |
286 NOTREACHED(); | |
287 } | |
288 | |
289 void NativeImageBufferEGL::DidWrite(gfx::GLImage* client) { | |
290 base::AutoLock lock(lock_); | |
291 // Sharing semantics require the client to flush in order to make changes | |
292 // visible to other clients. | |
293 write_fence_.reset(new gfx::GLFenceEGL(false)); | |
294 write_client_ = client; | |
295 for (std::list<ClientInfo>::iterator it = client_infos_.begin(); | |
296 it != client_infos_.end(); | |
297 it++) { | |
298 it->needs_wait_before_read = true; | |
299 } | |
300 } | |
301 | |
302 #endif | 227 #endif |
303 | 228 |
304 class NativeImageBufferStub : public NativeImageBuffer { | 229 class NativeImageBufferStub : public NativeImageBuffer { |
305 public: | 230 public: |
306 NativeImageBufferStub() : NativeImageBuffer() {} | 231 NativeImageBufferStub() : NativeImageBuffer() {} |
307 | 232 |
308 private: | 233 private: |
309 ~NativeImageBufferStub() override {} | 234 ~NativeImageBufferStub() override {} |
310 void AddClient(gfx::GLImage* client) override {} | 235 void AddClient(gfx::GLImage* client) override {} |
311 void RemoveClient(gfx::GLImage* client) override {} | 236 void RemoveClient(gfx::GLImage* client) override {} |
312 bool IsClient(gfx::GLImage* client) override { return true; } | 237 bool IsClient(gfx::GLImage* client) override { return true; } |
313 void BindToTexture(GLenum target) override {} | 238 void BindToTexture(GLenum target) override {} |
314 void WillRead(gfx::GLImage* client) override {} | |
315 void WillWrite(gfx::GLImage* client) override {} | |
316 void DidRead(gfx::GLImage* client) override {} | |
317 void DidWrite(gfx::GLImage* client) override {} | |
318 | 239 |
319 DISALLOW_COPY_AND_ASSIGN(NativeImageBufferStub); | 240 DISALLOW_COPY_AND_ASSIGN(NativeImageBufferStub); |
320 }; | 241 }; |
321 | 242 |
322 } // anonymous namespace | 243 } // anonymous namespace |
323 | 244 |
324 // static | 245 // static |
325 scoped_refptr<NativeImageBuffer> NativeImageBuffer::Create(GLuint texture_id) { | 246 scoped_refptr<NativeImageBuffer> NativeImageBuffer::Create(GLuint texture_id) { |
326 switch (gfx::GetGLImplementation()) { | 247 switch (gfx::GetGLImplementation()) { |
327 #if !defined(OS_MACOSX) | 248 #if !defined(OS_MACOSX) |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 | 409 |
489 // All structural changes should have orphaned the texture. | 410 // All structural changes should have orphaned the texture. |
490 if (image_buffer_.get() && !texture->GetLevelImage(texture->target(), 0)) | 411 if (image_buffer_.get() && !texture->GetLevelImage(texture->target(), 0)) |
491 return false; | 412 return false; |
492 | 413 |
493 return true; | 414 return true; |
494 } | 415 } |
495 | 416 |
496 } // namespace gles2 | 417 } // namespace gles2 |
497 } // namespace gpu | 418 } // namespace gpu |
OLD | NEW |