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