| 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/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
| 10 #include "base/memory/linked_ptr.h" | 10 #include "base/memory/linked_ptr.h" |
| 11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/synchronization/lock.h" | 12 #include "base/synchronization/lock.h" |
| 13 #include "base/threading/thread_local.h" | 13 #include "base/threading/thread_local.h" |
| 14 #include "gpu/command_buffer/service/texture_manager.h" | 14 #include "gpu/command_buffer/service/texture_manager.h" |
| 15 #include "ui/gl/gl_image.h" | 15 #include "ui/gl/gl_image.h" |
| 16 #include "ui/gl/gl_implementation.h" | 16 #include "ui/gl/gl_implementation.h" |
| 17 #include "ui/gl/scoped_binders.h" | 17 #include "ui/gl/scoped_binders.h" |
| 18 | 18 |
| 19 #if !defined(OS_MACOSX) | 19 #if !defined(OS_MACOSX) |
| 20 #include "ui/gl/gl_surface_egl.h" | 20 #include "ui/gl/gl_surface_egl.h" |
| 21 #endif | 21 #endif |
| 22 | 22 |
| 23 namespace gpu { | 23 namespace gpu { |
| 24 namespace gles2 { | 24 namespace gles2 { |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 class GLImageSync : public gfx::GLImage { | 28 class GLImageSync : public gl::GLImage { |
| 29 public: | 29 public: |
| 30 explicit GLImageSync(const scoped_refptr<NativeImageBuffer>& buffer, | 30 explicit GLImageSync(const scoped_refptr<NativeImageBuffer>& buffer, |
| 31 const gfx::Size& size); | 31 const gfx::Size& size); |
| 32 | 32 |
| 33 // Implement GLImage. | 33 // Implement GLImage. |
| 34 void Destroy(bool have_context) override; | 34 void Destroy(bool have_context) override; |
| 35 gfx::Size GetSize() override; | 35 gfx::Size GetSize() override; |
| 36 unsigned GetInternalFormat() override; | 36 unsigned GetInternalFormat() override; |
| 37 bool BindTexImage(unsigned target) override; | 37 bool BindTexImage(unsigned target) override; |
| 38 void ReleaseTexImage(unsigned target) override; | 38 void ReleaseTexImage(unsigned target) override; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 } | 117 } |
| 118 | 118 |
| 119 #if !defined(OS_MACOSX) | 119 #if !defined(OS_MACOSX) |
| 120 class NativeImageBufferEGL : public NativeImageBuffer { | 120 class NativeImageBufferEGL : public NativeImageBuffer { |
| 121 public: | 121 public: |
| 122 static scoped_refptr<NativeImageBufferEGL> Create(GLuint texture_id); | 122 static scoped_refptr<NativeImageBufferEGL> Create(GLuint texture_id); |
| 123 | 123 |
| 124 private: | 124 private: |
| 125 NativeImageBufferEGL(EGLDisplay display, EGLImageKHR image); | 125 NativeImageBufferEGL(EGLDisplay display, EGLImageKHR image); |
| 126 ~NativeImageBufferEGL() override; | 126 ~NativeImageBufferEGL() override; |
| 127 void AddClient(gfx::GLImage* client) override; | 127 void AddClient(gl::GLImage* client) override; |
| 128 void RemoveClient(gfx::GLImage* client) override; | 128 void RemoveClient(gl::GLImage* client) override; |
| 129 bool IsClient(gfx::GLImage* client) override; | 129 bool IsClient(gl::GLImage* client) override; |
| 130 void BindToTexture(GLenum target) const override; | 130 void BindToTexture(GLenum target) const override; |
| 131 | 131 |
| 132 const EGLDisplay egl_display_; | 132 const EGLDisplay egl_display_; |
| 133 const EGLImageKHR egl_image_; | 133 const EGLImageKHR egl_image_; |
| 134 | 134 |
| 135 base::Lock lock_; | 135 base::Lock lock_; |
| 136 | 136 |
| 137 struct ClientInfo { | 137 struct ClientInfo { |
| 138 explicit ClientInfo(gfx::GLImage* client); | 138 explicit ClientInfo(gl::GLImage* client); |
| 139 ~ClientInfo(); | 139 ~ClientInfo(); |
| 140 | 140 |
| 141 gfx::GLImage* client; | 141 gl::GLImage* client; |
| 142 bool needs_wait_before_read; | 142 bool needs_wait_before_read; |
| 143 }; | 143 }; |
| 144 std::list<ClientInfo> client_infos_; | 144 std::list<ClientInfo> client_infos_; |
| 145 gfx::GLImage* write_client_; | 145 gl::GLImage* write_client_; |
| 146 | 146 |
| 147 DISALLOW_COPY_AND_ASSIGN(NativeImageBufferEGL); | 147 DISALLOW_COPY_AND_ASSIGN(NativeImageBufferEGL); |
| 148 }; | 148 }; |
| 149 | 149 |
| 150 scoped_refptr<NativeImageBufferEGL> NativeImageBufferEGL::Create( | 150 scoped_refptr<NativeImageBufferEGL> NativeImageBufferEGL::Create( |
| 151 GLuint texture_id) { | 151 GLuint texture_id) { |
| 152 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); | 152 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); |
| 153 EGLContext egl_context = eglGetCurrentContext(); | 153 EGLContext egl_context = eglGetCurrentContext(); |
| 154 | 154 |
| 155 DCHECK_NE(EGL_NO_CONTEXT, egl_context); | 155 DCHECK_NE(EGL_NO_CONTEXT, egl_context); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 170 | 170 |
| 171 if (egl_image == EGL_NO_IMAGE_KHR) { | 171 if (egl_image == EGL_NO_IMAGE_KHR) { |
| 172 LOG(ERROR) << "eglCreateImageKHR for cross-thread sharing failed: 0x" | 172 LOG(ERROR) << "eglCreateImageKHR for cross-thread sharing failed: 0x" |
| 173 << std::hex << eglGetError(); | 173 << std::hex << eglGetError(); |
| 174 return NULL; | 174 return NULL; |
| 175 } | 175 } |
| 176 | 176 |
| 177 return new NativeImageBufferEGL(egl_display, egl_image); | 177 return new NativeImageBufferEGL(egl_display, egl_image); |
| 178 } | 178 } |
| 179 | 179 |
| 180 NativeImageBufferEGL::ClientInfo::ClientInfo(gfx::GLImage* client) | 180 NativeImageBufferEGL::ClientInfo::ClientInfo(gl::GLImage* client) |
| 181 : client(client), needs_wait_before_read(true) {} | 181 : client(client), needs_wait_before_read(true) {} |
| 182 | 182 |
| 183 NativeImageBufferEGL::ClientInfo::~ClientInfo() {} | 183 NativeImageBufferEGL::ClientInfo::~ClientInfo() {} |
| 184 | 184 |
| 185 NativeImageBufferEGL::NativeImageBufferEGL(EGLDisplay display, | 185 NativeImageBufferEGL::NativeImageBufferEGL(EGLDisplay display, |
| 186 EGLImageKHR image) | 186 EGLImageKHR image) |
| 187 : NativeImageBuffer(), | 187 : NativeImageBuffer(), |
| 188 egl_display_(display), | 188 egl_display_(display), |
| 189 egl_image_(image), | 189 egl_image_(image), |
| 190 write_client_(NULL) { | 190 write_client_(NULL) { |
| 191 DCHECK(egl_display_ != EGL_NO_DISPLAY); | 191 DCHECK(egl_display_ != EGL_NO_DISPLAY); |
| 192 DCHECK(egl_image_ != EGL_NO_IMAGE_KHR); | 192 DCHECK(egl_image_ != EGL_NO_IMAGE_KHR); |
| 193 } | 193 } |
| 194 | 194 |
| 195 NativeImageBufferEGL::~NativeImageBufferEGL() { | 195 NativeImageBufferEGL::~NativeImageBufferEGL() { |
| 196 DCHECK(client_infos_.empty()); | 196 DCHECK(client_infos_.empty()); |
| 197 if (egl_image_ != EGL_NO_IMAGE_KHR) | 197 if (egl_image_ != EGL_NO_IMAGE_KHR) |
| 198 eglDestroyImageKHR(egl_display_, egl_image_); | 198 eglDestroyImageKHR(egl_display_, egl_image_); |
| 199 } | 199 } |
| 200 | 200 |
| 201 void NativeImageBufferEGL::AddClient(gfx::GLImage* client) { | 201 void NativeImageBufferEGL::AddClient(gl::GLImage* client) { |
| 202 base::AutoLock lock(lock_); | 202 base::AutoLock lock(lock_); |
| 203 client_infos_.push_back(ClientInfo(client)); | 203 client_infos_.push_back(ClientInfo(client)); |
| 204 } | 204 } |
| 205 | 205 |
| 206 void NativeImageBufferEGL::RemoveClient(gfx::GLImage* client) { | 206 void NativeImageBufferEGL::RemoveClient(gl::GLImage* client) { |
| 207 base::AutoLock lock(lock_); | 207 base::AutoLock lock(lock_); |
| 208 if (write_client_ == client) | 208 if (write_client_ == client) |
| 209 write_client_ = NULL; | 209 write_client_ = NULL; |
| 210 for (std::list<ClientInfo>::iterator it = client_infos_.begin(); | 210 for (std::list<ClientInfo>::iterator it = client_infos_.begin(); |
| 211 it != client_infos_.end(); | 211 it != client_infos_.end(); |
| 212 it++) { | 212 it++) { |
| 213 if (it->client == client) { | 213 if (it->client == client) { |
| 214 client_infos_.erase(it); | 214 client_infos_.erase(it); |
| 215 return; | 215 return; |
| 216 } | 216 } |
| 217 } | 217 } |
| 218 NOTREACHED(); | 218 NOTREACHED(); |
| 219 } | 219 } |
| 220 | 220 |
| 221 bool NativeImageBufferEGL::IsClient(gfx::GLImage* client) { | 221 bool NativeImageBufferEGL::IsClient(gl::GLImage* client) { |
| 222 base::AutoLock lock(lock_); | 222 base::AutoLock lock(lock_); |
| 223 for (std::list<ClientInfo>::iterator it = client_infos_.begin(); | 223 for (std::list<ClientInfo>::iterator it = client_infos_.begin(); |
| 224 it != client_infos_.end(); | 224 it != client_infos_.end(); |
| 225 it++) { | 225 it++) { |
| 226 if (it->client == client) | 226 if (it->client == client) |
| 227 return true; | 227 return true; |
| 228 } | 228 } |
| 229 return false; | 229 return false; |
| 230 } | 230 } |
| 231 | 231 |
| 232 void NativeImageBufferEGL::BindToTexture(GLenum target) const { | 232 void NativeImageBufferEGL::BindToTexture(GLenum target) const { |
| 233 DCHECK(egl_image_ != EGL_NO_IMAGE_KHR); | 233 DCHECK(egl_image_ != EGL_NO_IMAGE_KHR); |
| 234 glEGLImageTargetTexture2DOES(target, egl_image_); | 234 glEGLImageTargetTexture2DOES(target, egl_image_); |
| 235 DCHECK_EQ(static_cast<EGLint>(EGL_SUCCESS), eglGetError()); | 235 DCHECK_EQ(static_cast<EGLint>(EGL_SUCCESS), eglGetError()); |
| 236 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | 236 DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); |
| 237 } | 237 } |
| 238 | 238 |
| 239 #endif | 239 #endif |
| 240 | 240 |
| 241 class NativeImageBufferStub : public NativeImageBuffer { | 241 class NativeImageBufferStub : public NativeImageBuffer { |
| 242 public: | 242 public: |
| 243 NativeImageBufferStub() : NativeImageBuffer() {} | 243 NativeImageBufferStub() : NativeImageBuffer() {} |
| 244 | 244 |
| 245 private: | 245 private: |
| 246 ~NativeImageBufferStub() override {} | 246 ~NativeImageBufferStub() override {} |
| 247 void AddClient(gfx::GLImage* client) override {} | 247 void AddClient(gl::GLImage* client) override {} |
| 248 void RemoveClient(gfx::GLImage* client) override {} | 248 void RemoveClient(gl::GLImage* client) override {} |
| 249 bool IsClient(gfx::GLImage* client) override { return true; } | 249 bool IsClient(gl::GLImage* client) override { return true; } |
| 250 void BindToTexture(GLenum target) const override {} | 250 void BindToTexture(GLenum target) const override {} |
| 251 | 251 |
| 252 DISALLOW_COPY_AND_ASSIGN(NativeImageBufferStub); | 252 DISALLOW_COPY_AND_ASSIGN(NativeImageBufferStub); |
| 253 }; | 253 }; |
| 254 | 254 |
| 255 bool g_avoid_egl_target_texture_reuse = false; | 255 bool g_avoid_egl_target_texture_reuse = false; |
| 256 | 256 |
| 257 } // anonymous namespace | 257 } // anonymous namespace |
| 258 | 258 |
| 259 // static | 259 // static |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 immutable_(texture->IsImmutable()), | 335 immutable_(texture->IsImmutable()), |
| 336 defined_(texture->IsDefined()) { | 336 defined_(texture->IsDefined()) { |
| 337 DCHECK_IMPLIES(image_buffer_.get(), defined_); | 337 DCHECK_IMPLIES(image_buffer_.get(), defined_); |
| 338 if (!image_buffer_.get() && defined_) { | 338 if (!image_buffer_.get() && defined_) { |
| 339 image_buffer_ = NativeImageBuffer::Create(texture->service_id()); | 339 image_buffer_ = NativeImageBuffer::Create(texture->service_id()); |
| 340 DCHECK(image_buffer_.get()); | 340 DCHECK(image_buffer_.get()); |
| 341 } | 341 } |
| 342 | 342 |
| 343 const Texture::FaceInfo& first_face = texture->face_infos_[0]; | 343 const Texture::FaceInfo& first_face = texture->face_infos_[0]; |
| 344 if (image_buffer_.get()) { | 344 if (image_buffer_.get()) { |
| 345 scoped_refptr<gfx::GLImage> gl_image( | 345 scoped_refptr<gl::GLImage> gl_image( |
| 346 new GLImageSync(image_buffer_, | 346 new GLImageSync(image_buffer_, |
| 347 gfx::Size(first_face.level_infos[0].width, | 347 gfx::Size(first_face.level_infos[0].width, |
| 348 first_face.level_infos[0].height))); | 348 first_face.level_infos[0].height))); |
| 349 texture->SetLevelImage(target_, 0, gl_image.get(), Texture::BOUND); | 349 texture->SetLevelImage(target_, 0, gl_image.get(), Texture::BOUND); |
| 350 } | 350 } |
| 351 | 351 |
| 352 const Texture::LevelInfo& level = first_face.level_infos[0]; | 352 const Texture::LevelInfo& level = first_face.level_infos[0]; |
| 353 level_info_ = LevelInfo(level.target, level.internal_format, level.width, | 353 level_info_ = LevelInfo(level.target, level.internal_format, level.width, |
| 354 level.height, level.depth, level.border, level.format, | 354 level.height, level.depth, level.border, level.format, |
| 355 level.type, level.cleared_rect); | 355 level.type, level.cleared_rect); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 369 } | 369 } |
| 370 | 370 |
| 371 void TextureDefinition::UpdateTextureInternal(Texture* texture) const { | 371 void TextureDefinition::UpdateTextureInternal(Texture* texture) const { |
| 372 gfx::ScopedTextureBinder texture_binder(target_, texture->service_id()); | 372 gfx::ScopedTextureBinder texture_binder(target_, texture->service_id()); |
| 373 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_); | 373 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_); |
| 374 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_); | 374 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_); |
| 375 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s_); | 375 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s_); |
| 376 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t_); | 376 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t_); |
| 377 | 377 |
| 378 if (image_buffer_.get()) { | 378 if (image_buffer_.get()) { |
| 379 gfx::GLImage* existing_image = texture->GetLevelImage(target_, 0); | 379 gl::GLImage* existing_image = texture->GetLevelImage(target_, 0); |
| 380 // Don't need to re-bind if already bound before. | 380 // Don't need to re-bind if already bound before. |
| 381 if (!existing_image || !image_buffer_->IsClient(existing_image)) { | 381 if (!existing_image || !image_buffer_->IsClient(existing_image)) { |
| 382 image_buffer_->BindToTexture(target_); | 382 image_buffer_->BindToTexture(target_); |
| 383 } | 383 } |
| 384 } | 384 } |
| 385 | 385 |
| 386 if (defined_) { | 386 if (defined_) { |
| 387 texture->face_infos_.resize(1); | 387 texture->face_infos_.resize(1); |
| 388 texture->face_infos_[0].level_infos.resize(1); | 388 texture->face_infos_[0].level_infos.resize(1); |
| 389 texture->SetLevelInfo(NULL, level_info_.target, 0, | 389 texture->SetLevelInfo(NULL, level_info_.target, 0, |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 return true; | 455 return true; |
| 456 } | 456 } |
| 457 | 457 |
| 458 bool TextureDefinition::SafeToRenderFrom() const { | 458 bool TextureDefinition::SafeToRenderFrom() const { |
| 459 return level_info_.cleared_rect.Contains( | 459 return level_info_.cleared_rect.Contains( |
| 460 gfx::Rect(level_info_.width, level_info_.height)); | 460 gfx::Rect(level_info_.width, level_info_.height)); |
| 461 } | 461 } |
| 462 | 462 |
| 463 } // namespace gles2 | 463 } // namespace gles2 |
| 464 } // namespace gpu | 464 } // namespace gpu |
| OLD | NEW |