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" |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 gfx::g_driver_gl.ext.b_GL_OES_EGL_image); | 152 gfx::g_driver_gl.ext.b_GL_OES_EGL_image); |
153 | 153 |
154 const EGLint egl_attrib_list[] = { | 154 const EGLint egl_attrib_list[] = { |
155 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}; |
156 EGLClientBuffer egl_buffer = reinterpret_cast<EGLClientBuffer>(texture_id); | 156 EGLClientBuffer egl_buffer = reinterpret_cast<EGLClientBuffer>(texture_id); |
157 EGLenum egl_target = EGL_GL_TEXTURE_2D_KHR; // TODO | 157 EGLenum egl_target = EGL_GL_TEXTURE_2D_KHR; // TODO |
158 | 158 |
159 EGLImageKHR egl_image = eglCreateImageKHR( | 159 EGLImageKHR egl_image = eglCreateImageKHR( |
160 egl_display, egl_context, egl_target, egl_buffer, egl_attrib_list); | 160 egl_display, egl_context, egl_target, egl_buffer, egl_attrib_list); |
161 | 161 |
162 if (egl_image == EGL_NO_IMAGE_KHR) | 162 if (egl_image == EGL_NO_IMAGE_KHR) { |
| 163 LOG(ERROR) << "eglCreateImageKHR for cross-thread sharing failed: 0x" |
| 164 << std::hex << eglGetError(); |
163 return NULL; | 165 return NULL; |
| 166 } |
164 | 167 |
165 return new NativeImageBufferEGL(egl_display, egl_image); | 168 return new NativeImageBufferEGL(egl_display, egl_image); |
166 } | 169 } |
167 | 170 |
168 NativeImageBufferEGL::ClientInfo::ClientInfo(gfx::GLImage* client) | 171 NativeImageBufferEGL::ClientInfo::ClientInfo(gfx::GLImage* client) |
169 : client(client), needs_wait_before_read(true) {} | 172 : client(client), needs_wait_before_read(true) {} |
170 | 173 |
171 NativeImageBufferEGL::ClientInfo::~ClientInfo() {} | 174 NativeImageBufferEGL::ClientInfo::~ClientInfo() {} |
172 | 175 |
173 NativeImageBufferEGL::NativeImageBufferEGL(EGLDisplay display, | 176 NativeImageBufferEGL::NativeImageBufferEGL(EGLDisplay display, |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 return NativeImageBufferEGL::Create(texture_id); | 253 return NativeImageBufferEGL::Create(texture_id); |
251 #endif | 254 #endif |
252 case gfx::kGLImplementationMockGL: | 255 case gfx::kGLImplementationMockGL: |
253 return new NativeImageBufferStub; | 256 return new NativeImageBufferStub; |
254 default: | 257 default: |
255 NOTREACHED(); | 258 NOTREACHED(); |
256 return NULL; | 259 return NULL; |
257 } | 260 } |
258 } | 261 } |
259 | 262 |
| 263 TextureDefinition::LevelInfo::LevelInfo() |
| 264 : target(0), |
| 265 internal_format(0), |
| 266 width(0), |
| 267 height(0), |
| 268 depth(0), |
| 269 border(0), |
| 270 format(0), |
| 271 type(0), |
| 272 cleared(false) { |
| 273 } |
| 274 |
260 TextureDefinition::LevelInfo::LevelInfo(GLenum target, | 275 TextureDefinition::LevelInfo::LevelInfo(GLenum target, |
261 GLenum internal_format, | 276 GLenum internal_format, |
262 GLsizei width, | 277 GLsizei width, |
263 GLsizei height, | 278 GLsizei height, |
264 GLsizei depth, | 279 GLsizei depth, |
265 GLint border, | 280 GLint border, |
266 GLenum format, | 281 GLenum format, |
267 GLenum type, | 282 GLenum type, |
268 bool cleared) | 283 bool cleared) |
269 : target(target), | 284 : target(target), |
(...skipping 18 matching lines...) Expand all Loading... |
288 usage_(0), | 303 usage_(0), |
289 immutable_(true) { | 304 immutable_(true) { |
290 } | 305 } |
291 | 306 |
292 TextureDefinition::TextureDefinition( | 307 TextureDefinition::TextureDefinition( |
293 Texture* texture, | 308 Texture* texture, |
294 unsigned int version, | 309 unsigned int version, |
295 const scoped_refptr<NativeImageBuffer>& image_buffer) | 310 const scoped_refptr<NativeImageBuffer>& image_buffer) |
296 : version_(version), | 311 : version_(version), |
297 target_(texture->target()), | 312 target_(texture->target()), |
298 image_buffer_(image_buffer.get() | 313 image_buffer_(image_buffer), |
299 ? image_buffer | |
300 : NativeImageBuffer::Create(texture->service_id())), | |
301 min_filter_(texture->min_filter()), | 314 min_filter_(texture->min_filter()), |
302 mag_filter_(texture->mag_filter()), | 315 mag_filter_(texture->mag_filter()), |
303 wrap_s_(texture->wrap_s()), | 316 wrap_s_(texture->wrap_s()), |
304 wrap_t_(texture->wrap_t()), | 317 wrap_t_(texture->wrap_t()), |
305 usage_(texture->usage()), | 318 usage_(texture->usage()), |
306 immutable_(texture->IsImmutable()) { | 319 immutable_(texture->IsImmutable()), |
307 // TODO | 320 defined_(texture->IsDefined()) { |
308 DCHECK(!texture->face_infos_.empty()); | 321 DCHECK_IMPLIES(image_buffer_.get(), defined_); |
309 DCHECK(!texture->face_infos_[0].level_infos.empty()); | 322 if (!image_buffer_.get() && defined_) { |
310 DCHECK(!texture->NeedsMips()); | 323 image_buffer_ = NativeImageBuffer::Create(texture->service_id()); |
311 DCHECK(texture->face_infos_[0].level_infos[0].width); | 324 DCHECK(image_buffer_.get()); |
312 DCHECK(texture->face_infos_[0].level_infos[0].height); | 325 } |
313 | 326 |
314 const Texture::FaceInfo& first_face = texture->face_infos_[0]; | 327 const Texture::FaceInfo& first_face = texture->face_infos_[0]; |
315 scoped_refptr<gfx::GLImage> gl_image( | 328 if (image_buffer_.get()) { |
316 new GLImageSync(image_buffer_, | 329 scoped_refptr<gfx::GLImage> gl_image( |
317 gfx::Size(first_face.level_infos[0].width, | 330 new GLImageSync(image_buffer_, |
318 first_face.level_infos[0].height))); | 331 gfx::Size(first_face.level_infos[0].width, |
319 texture->SetLevelImage(NULL, target_, 0, gl_image.get()); | 332 first_face.level_infos[0].height))); |
| 333 texture->SetLevelImage(NULL, target_, 0, gl_image.get()); |
| 334 } |
320 | 335 |
321 // TODO: all levels | |
322 level_infos_.clear(); | |
323 const Texture::LevelInfo& level = first_face.level_infos[0]; | 336 const Texture::LevelInfo& level = first_face.level_infos[0]; |
324 LevelInfo info(level.target, | 337 level_info_ = LevelInfo(level.target, level.internal_format, level.width, |
325 level.internal_format, | 338 level.height, level.depth, level.border, level.format, |
326 level.width, | 339 level.type, level.cleared); |
327 level.height, | |
328 level.depth, | |
329 level.border, | |
330 level.format, | |
331 level.type, | |
332 level.cleared); | |
333 std::vector<LevelInfo> infos; | |
334 infos.push_back(info); | |
335 level_infos_.push_back(infos); | |
336 } | 340 } |
337 | 341 |
338 TextureDefinition::~TextureDefinition() { | 342 TextureDefinition::~TextureDefinition() { |
339 } | 343 } |
340 | 344 |
341 Texture* TextureDefinition::CreateTexture() const { | 345 Texture* TextureDefinition::CreateTexture() const { |
342 if (!image_buffer_.get()) | |
343 return NULL; | |
344 | |
345 GLuint texture_id; | 346 GLuint texture_id; |
346 glGenTextures(1, &texture_id); | 347 glGenTextures(1, &texture_id); |
347 | 348 |
348 Texture* texture(new Texture(texture_id)); | 349 Texture* texture(new Texture(texture_id)); |
349 UpdateTexture(texture); | 350 UpdateTexture(texture); |
350 | 351 |
351 return texture; | 352 return texture; |
352 } | 353 } |
353 | 354 |
354 void TextureDefinition::UpdateTexture(Texture* texture) const { | 355 void TextureDefinition::UpdateTexture(Texture* texture) const { |
355 gfx::ScopedTextureBinder texture_binder(target_, texture->service_id()); | 356 gfx::ScopedTextureBinder texture_binder(target_, texture->service_id()); |
356 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_); | 357 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_); |
357 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_); | 358 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_); |
358 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s_); | 359 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s_); |
359 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t_); | 360 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t_); |
360 if (image_buffer_.get()) | 361 if (image_buffer_.get()) |
361 image_buffer_->BindToTexture(target_); | 362 image_buffer_->BindToTexture(target_); |
362 // We have to make sure the changes are visible to other clients in this share | 363 // We have to make sure the changes are visible to other clients in this share |
363 // group. As far as the clients are concerned, the mailbox semantics only | 364 // group. As far as the clients are concerned, the mailbox semantics only |
364 // demand a single flush from the client after changes are first made, | 365 // demand a single flush from the client after changes are first made, |
365 // and it is not visible to them when another share group boundary is crossed. | 366 // and it is not visible to them when another share group boundary is crossed. |
366 // We could probably track this and be a bit smarter about when to flush | 367 // We could probably track this and be a bit smarter about when to flush |
367 // though. | 368 // though. |
368 glFlush(); | 369 glFlush(); |
369 | 370 |
370 texture->face_infos_.resize(1); | 371 if (defined_) { |
371 for (size_t i = 0; i < level_infos_.size(); i++) { | 372 texture->face_infos_.resize(1); |
372 const LevelInfo& base_info = level_infos_[i][0]; | 373 texture->face_infos_[0].level_infos.resize(1); |
373 const size_t levels_needed = TextureManager::ComputeMipMapCount( | 374 texture->SetLevelInfo(NULL, level_info_.target, 0, |
374 base_info.target, base_info.width, base_info.height, base_info.depth); | 375 level_info_.internal_format, level_info_.width, |
375 DCHECK(level_infos_.size() <= levels_needed); | 376 level_info_.height, level_info_.depth, |
376 texture->face_infos_[0].level_infos.resize(levels_needed); | 377 level_info_.border, level_info_.format, |
377 for (size_t n = 0; n < level_infos_.size(); n++) { | 378 level_info_.type, level_info_.cleared); |
378 const LevelInfo& info = level_infos_[i][n]; | |
379 texture->SetLevelInfo(NULL, | |
380 info.target, | |
381 i, | |
382 info.internal_format, | |
383 info.width, | |
384 info.height, | |
385 info.depth, | |
386 info.border, | |
387 info.format, | |
388 info.type, | |
389 info.cleared); | |
390 } | |
391 } | 379 } |
| 380 |
392 if (image_buffer_.get()) { | 381 if (image_buffer_.get()) { |
393 texture->SetLevelImage( | 382 texture->SetLevelImage( |
394 NULL, | 383 NULL, |
395 target_, | 384 target_, |
396 0, | 385 0, |
397 new GLImageSync( | 386 new GLImageSync( |
398 image_buffer_, | 387 image_buffer_, |
399 gfx::Size(level_infos_[0][0].width, level_infos_[0][0].height))); | 388 gfx::Size(level_info_.width, level_info_.height))); |
400 } | 389 } |
401 | 390 |
402 texture->target_ = target_; | 391 texture->target_ = target_; |
403 texture->SetImmutable(immutable_); | 392 texture->SetImmutable(immutable_); |
404 texture->min_filter_ = min_filter_; | 393 texture->min_filter_ = min_filter_; |
405 texture->mag_filter_ = mag_filter_; | 394 texture->mag_filter_ = mag_filter_; |
406 texture->wrap_s_ = wrap_s_; | 395 texture->wrap_s_ = wrap_s_; |
407 texture->wrap_t_ = wrap_t_; | 396 texture->wrap_t_ = wrap_t_; |
408 texture->usage_ = usage_; | 397 texture->usage_ = usage_; |
409 } | 398 } |
410 | 399 |
411 bool TextureDefinition::Matches(const Texture* texture) const { | 400 bool TextureDefinition::Matches(const Texture* texture) const { |
412 DCHECK(target_ == texture->target()); | 401 DCHECK(target_ == texture->target()); |
413 if (texture->min_filter_ != min_filter_ || | 402 if (texture->min_filter_ != min_filter_ || |
414 texture->mag_filter_ != mag_filter_ || | 403 texture->mag_filter_ != mag_filter_ || |
415 texture->wrap_s_ != wrap_s_ || | 404 texture->wrap_s_ != wrap_s_ || |
416 texture->wrap_t_ != wrap_t_ || | 405 texture->wrap_t_ != wrap_t_ || |
417 texture->SafeToRenderFrom() != SafeToRenderFrom()) { | 406 texture->SafeToRenderFrom() != SafeToRenderFrom()) { |
418 return false; | 407 return false; |
419 } | 408 } |
420 | 409 |
| 410 // Texture became defined. |
| 411 if (!image_buffer_.get() && texture->IsDefined()) |
| 412 return false; |
| 413 |
421 // All structural changes should have orphaned the texture. | 414 // All structural changes should have orphaned the texture. |
422 if (image_buffer_.get() && !texture->GetLevelImage(texture->target(), 0)) | 415 if (image_buffer_.get() && !texture->GetLevelImage(texture->target(), 0)) |
423 return false; | 416 return false; |
424 | 417 |
425 return true; | 418 return true; |
426 } | 419 } |
427 | 420 |
428 bool TextureDefinition::SafeToRenderFrom() const { | 421 bool TextureDefinition::SafeToRenderFrom() const { |
429 for (const std::vector<LevelInfo>& face_info : level_infos_) { | 422 return level_info_.cleared; |
430 for (const LevelInfo& level_info : face_info) { | |
431 if (!level_info.cleared) { | |
432 return false; | |
433 } | |
434 } | |
435 } | |
436 return true; | |
437 } | 423 } |
438 | 424 |
439 } // namespace gles2 | 425 } // namespace gles2 |
440 } // namespace gpu | 426 } // namespace gpu |
OLD | NEW |