Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(75)

Side by Side Diff: gpu/command_buffer/service/texture_definition.cc

Issue 180723023: gpu: Mailbox emulation with EGLImage (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "gpu/command_buffer/service/texture_definition.h"
6
7 #include "gpu/command_buffer/service/texture_manager.h"
8 #include "ui/gl/gl_image.h"
9 #include "ui/gl/gl_implementation.h"
10 #include "ui/gl/gl_surface_egl.h"
11 #include "ui/gl/scoped_binders.h"
12
13 namespace gpu {
14 namespace gles2 {
15
16 namespace {
17
18 class GLImageSync : public gfx::GLImage {
19 public:
20 explicit GLImageSync(
21 const scoped_refptr<NativeImageBuffer>& buffer);
22
23 // Implement GLImage.
24 virtual void Destroy() OVERRIDE;
25 virtual gfx::Size GetSize() OVERRIDE;
26 virtual bool BindTexImage(unsigned target) OVERRIDE;
27 virtual void ReleaseTexImage(unsigned target) OVERRIDE;
28 virtual void WillUseTexImage() OVERRIDE;
29 virtual void WillModifyPixels() OVERRIDE;
30 virtual void DidModifyPixels() OVERRIDE;
31
32 virtual void DidUseTexImage() OVERRIDE;
33 virtual void SetReleaseAfterUse() OVERRIDE;
34
35 protected:
36 virtual ~GLImageSync();
37
38 private:
39 scoped_refptr<NativeImageBuffer> buffer_;
40
41 DISALLOW_COPY_AND_ASSIGN(GLImageSync);
42 };
43
44 GLImageSync::GLImageSync(const scoped_refptr<NativeImageBuffer>& buffer)
45 : buffer_(buffer) {
46 if (buffer)
47 buffer->AddClient(this);
48 }
49
50 GLImageSync::~GLImageSync() {
51 if (buffer_)
52 buffer_->RemoveClient(this);
53 }
54
55 void GLImageSync::Destroy() {}
56
57 gfx::Size GLImageSync::GetSize() {
58 NOTREACHED();
59 return gfx::Size();
60 }
61
62 bool GLImageSync::BindTexImage(unsigned target) {
63 NOTREACHED();
64 return false;
65 }
66
67 void GLImageSync::ReleaseTexImage(unsigned target) {
68 NOTREACHED();
69 }
70
71 void GLImageSync::WillUseTexImage() {
72 if (buffer_)
73 buffer_->WillRead(this);
74 }
75
76 void GLImageSync::DidUseTexImage() {
77 if (buffer_)
78 buffer_->DidRead(this);
79 }
80
81 void GLImageSync::WillModifyPixels() {
82 if (buffer_)
83 buffer_->WillWrite(this);
84 }
85
86 void GLImageSync::DidModifyPixels() {
87 if (buffer_)
88 buffer_->DidWrite(this);
89 }
90
91 void GLImageSync::SetReleaseAfterUse() {
92 NOTREACHED();
93 }
94
95 class NativeImageBufferEGL : public NativeImageBuffer {
96 public:
97 static NativeImageBufferEGL* Create(GLuint texture_id);
98
99 private:
100 explicit NativeImageBufferEGL(EGLDisplay display, EGLImageKHR image);
101 virtual ~NativeImageBufferEGL();
102 virtual void BindToTexture(GLenum target) OVERRIDE;
103
104 EGLDisplay egl_display_;
105 EGLImageKHR egl_image_;
106
107 DISALLOW_COPY_AND_ASSIGN(NativeImageBufferEGL);
108 };
109
110 NativeImageBufferEGL* NativeImageBufferEGL::Create(GLuint texture_id) {
111 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
112 EGLContext egl_context = eglGetCurrentContext();
113
114 if (egl_context == EGL_NO_CONTEXT || egl_display == EGL_NO_DISPLAY ||
115 !glIsTexture(texture_id)) {
116 return NULL;
117 }
118
119 if (!gfx::g_driver_egl.ext.b_EGL_KHR_image_base ||
120 !gfx::g_driver_gl.ext.b_GL_OES_EGL_image) {
121 return NULL;
122 }
123
124 const EGLint egl_attrib_list[] = {
125 EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
126 EGLClientBuffer egl_buffer = reinterpret_cast<EGLClientBuffer>(texture_id);
127 EGLenum egl_target = EGL_GL_TEXTURE_2D_KHR; // TODO
128
129 EGLImageKHR egl_image = eglCreateImageKHR(
130 egl_display, egl_context, egl_target, egl_buffer, egl_attrib_list);
131
132 if (egl_image == EGL_NO_IMAGE_KHR)
133 return NULL;
134
135 return new NativeImageBufferEGL(egl_display, egl_image);
136 }
137
138 NativeImageBufferEGL::NativeImageBufferEGL(EGLDisplay display,
139 EGLImageKHR image)
140 : egl_display_(display), egl_image_(image) {
141 DCHECK(egl_display_ != EGL_NO_DISPLAY);
142 DCHECK(egl_image_ != EGL_NO_IMAGE_KHR);
143 }
144
145 NativeImageBufferEGL::~NativeImageBufferEGL() {
146 if (egl_image_ != EGL_NO_IMAGE_KHR)
147 eglDestroyImageKHR(egl_display_, egl_image_);
148 }
149
150 void NativeImageBufferEGL::BindToTexture(GLenum target) {
151 DCHECK(egl_image_ != EGL_NO_IMAGE_KHR);
152 glEGLImageTargetTexture2DOES(target, egl_image_);
153 DCHECK_EQ(EGL_SUCCESS, (EGLint)eglGetError());
154 DCHECK_EQ(GL_NO_ERROR, (GLint)glGetError());
155 }
156
157 class NativeImageBufferStub : public NativeImageBuffer {
158 public:
159 NativeImageBufferStub() {}
160
161 private:
162 virtual ~NativeImageBufferStub() {}
163 virtual void BindToTexture(GLenum target) OVERRIDE {}
164
165 DISALLOW_COPY_AND_ASSIGN(NativeImageBufferStub);
166 };
167
168 } // anonymous namespace
169
170 // static
171 NativeImageBuffer* NativeImageBuffer::Create(GLuint texture_id) {
172 switch (gfx::GetGLImplementation()) {
173 case gfx::kGLImplementationEGLGLES2:
174 return NativeImageBufferEGL::Create(texture_id);
175 case gfx::kGLImplementationMockGL:
176 return new NativeImageBufferStub;
177 default:
178 NOTREACHED();
179 return NULL;
180 }
181 }
182
183 NativeImageBuffer::ClientInfo::ClientInfo(gfx::GLImage* client)
184 : client(client), needs_wait_before_read(true) {}
185
186 NativeImageBuffer::ClientInfo::~ClientInfo() {}
187
188 NativeImageBuffer::NativeImageBuffer() : write_client_(NULL) {
189 write_fence_.reset(gfx::GLFence::Create());
190 }
191
192 NativeImageBuffer::~NativeImageBuffer() {
193 DCHECK(client_infos_.empty());
194 }
195
196 void NativeImageBuffer::AddClient(gfx::GLImage* client) {
197 base::AutoLock lock(lock_);
198 client_infos_.push_back(ClientInfo(client));
199 }
200
201 void NativeImageBuffer::RemoveClient(gfx::GLImage* client) {
202 base::AutoLock lock(lock_);
203 if (write_client_ == client)
204 write_client_ = NULL;
205 for (std::list<ClientInfo>::iterator it = client_infos_.begin();
206 it != client_infos_.end();
207 it++) {
208 if (it->client == client) {
209 client_infos_.erase(it);
210 return;
211 }
212 }
213 NOTREACHED();
214 }
215
216 bool NativeImageBuffer::IsClient(gfx::GLImage* client) {
217 base::AutoLock lock(lock_);
218 for (std::list<ClientInfo>::iterator it = client_infos_.begin();
219 it != client_infos_.end();
220 it++) {
221 if (it->client == client)
222 return true;
223 }
224 return false;
225 }
226
227 void NativeImageBuffer::WillRead(gfx::GLImage* client) {
228 base::AutoLock lock(lock_);
229 if (!write_fence_.get() || write_client_ == client)
230 return;
231
232 for (std::list<ClientInfo>::iterator it = client_infos_.begin();
233 it != client_infos_.end();
234 it++) {
235 if (it->client == client) {
236 if (it->needs_wait_before_read) {
237 it->needs_wait_before_read = false;
238 write_fence_->ServerWait();
239 }
240 return;
241 }
242 }
243 NOTREACHED();
244 }
245
246 void NativeImageBuffer::WillWrite(gfx::GLImage* client) {
247 base::AutoLock lock(lock_);
248 if (write_client_ != client)
249 write_fence_->ServerWait();
250
251 for (std::list<ClientInfo>::iterator it = client_infos_.begin();
252 it != client_infos_.end();
253 it++) {
254 if (it->read_fence.get() && it->client != client)
255 it->read_fence->ServerWait();
256 }
257 }
258
259 void NativeImageBuffer::DidRead(gfx::GLImage* client) {
260 base::AutoLock lock(lock_);
261 for (std::list<ClientInfo>::iterator it = client_infos_.begin();
262 it != client_infos_.end();
263 it++) {
264 if (it->client == client) {
265 it->read_fence = make_linked_ptr(gfx::GLFence::Create());
266 return;
267 }
268 }
269 NOTREACHED();
270 }
271
272 void NativeImageBuffer::DidWrite(gfx::GLImage* client) {
273 base::AutoLock lock(lock_);
274 // TODO(sievers): This is super-risky. We need to somehow find out
275 // about when the current context gets flushed, so that we will only
276 // ever wait on the write fence (esp. from another context) if it was
277 // flushed and is guaranteed to clear.
278 // On the other hand, proactively flushing here is not feasible in terms
279 // of perf when there are multiple draw calls per frame.
280 write_fence_.reset(gfx::GLFence::CreateWithoutFlush());
281 write_client_ = client;
282 for (std::list<ClientInfo>::iterator it = client_infos_.begin();
283 it != client_infos_.end();
284 it++) {
285 it->needs_wait_before_read = true;
286 }
287 }
288
289 TextureDefinition::LevelInfo::LevelInfo(GLenum target,
290 GLenum internal_format,
291 GLsizei width,
292 GLsizei height,
293 GLsizei depth,
294 GLint border,
295 GLenum format,
296 GLenum type,
297 bool cleared)
298 : target(target),
299 internal_format(internal_format),
300 width(width),
301 height(height),
302 depth(depth),
303 border(border),
304 format(format),
305 type(type),
306 cleared(cleared) {}
307
308 TextureDefinition::LevelInfo::~LevelInfo() {}
309
310 TextureDefinition::TextureDefinition(GLenum target,
311 Texture* texture,
312 unsigned int version,
313 NativeImageBuffer* image)
314 : version_(version),
315 target_(target),
316 image_(image ? image : NativeImageBuffer::Create(texture->service_id())),
317 min_filter_(texture->min_filter()),
318 mag_filter_(texture->mag_filter()),
319 wrap_s_(texture->wrap_s()),
320 wrap_t_(texture->wrap_t()),
321 usage_(texture->usage()),
322 immutable_(texture->IsImmutable()) {
323
324 // TODO
325 DCHECK(!texture->level_infos_.empty());
326 DCHECK(!texture->level_infos_[0].empty());
327 DCHECK(!texture->NeedsMips());
328 DCHECK(texture->level_infos_[0][0].width);
329 DCHECK(texture->level_infos_[0][0].height);
330
331 scoped_refptr<gfx::GLImage> gl_image(new GLImageSync(image_));
332 texture->SetLevelImage(NULL, target, 0, gl_image);
333
334 // TODO: all levels
335 level_infos_.clear();
336 const Texture::LevelInfo& level = texture->level_infos_[0][0];
337 LevelInfo info(level.target,
338 level.internal_format,
339 level.width,
340 level.height,
341 level.depth,
342 level.border,
343 level.format,
344 level.type,
345 level.cleared);
346 std::vector<LevelInfo> infos;
347 infos.push_back(info);
348 level_infos_.push_back(infos);
349
350 }
351
352 TextureDefinition::~TextureDefinition() {
353 }
354
355 Texture* TextureDefinition::CreateTexture() const {
356 if (!image_)
357 return NULL;
358
359 GLuint texture_id;
360 glGenTextures(1, &texture_id);
361
362 Texture* texture(new Texture(texture_id));
363 UpdateTexture(texture);
364
365 return texture;
366 }
367
368 void TextureDefinition::UpdateTexture(Texture* texture) const {
369 gfx::ScopedTextureBinder texture_binder(target_, texture->service_id());
370 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_);
371 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_);
372 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s_);
373 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t_);
374 DCHECK(image_);
375 if (image_)
376 image_->BindToTexture(target_);
377 glFlush();
378
379 texture->level_infos_.resize(1);
380 for (size_t i = 0; i < level_infos_.size(); i++) {
381 const LevelInfo& base_info = level_infos_[i][0];
382 const size_t levels_needed = TextureManager::ComputeMipMapCount(
383 base_info.target, base_info.width, base_info.height, base_info.depth);
384 DCHECK(level_infos_.size() <= levels_needed);
385 texture->level_infos_[0].resize(levels_needed);
386 for (size_t n = 0; n < level_infos_.size(); n++) {
387 const LevelInfo& info = level_infos_[i][n];
388 texture->SetLevelInfo(NULL,
389 info.target,
390 i,
391 info.internal_format,
392 info.width,
393 info.height,
394 info.depth,
395 info.border,
396 info.format,
397 info.type,
398 info.cleared);
399 }
400 }
401 if (image_)
402 texture->SetLevelImage(NULL, target_, 0, new GLImageSync(image_));
403
404 texture->target_ = target_;
405 texture->SetImmutable(immutable_);
406 texture->min_filter_ = min_filter_;
407 texture->mag_filter_ = mag_filter_;
408 texture->wrap_s_ = wrap_s_;
409 texture->wrap_t_ = wrap_t_;
410 texture->usage_ = usage_;
411 }
412
413 bool TextureDefinition::Matches(const Texture* texture) const {
414 DCHECK(target_ == texture->target());
415 if (texture->min_filter_ != min_filter_ ||
416 texture->mag_filter_ != mag_filter_ ||
417 texture->wrap_s_ != wrap_s_ ||
418 texture->wrap_t_ != wrap_t_) {
419 return false;
420 }
421
422 // All structural changes should have orphaned the texture.
423 if (image_ && !texture->GetLevelImage(texture->target(), 0))
424 return false;
425
426 return true;
427 }
428
429 } // namespace gles2
430 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698