- add sources.
[platform/framework/web/crosswalk.git] / src / gpu / command_buffer / service / texture_manager.cc
1 // Copyright (c) 2012 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_manager.h"
6 #include "base/bits.h"
7 #include "base/strings/stringprintf.h"
8 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
9 #include "gpu/command_buffer/service/context_state.h"
10 #include "gpu/command_buffer/service/error_state.h"
11 #include "gpu/command_buffer/service/feature_info.h"
12 #include "gpu/command_buffer/service/framebuffer_manager.h"
13 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
14 #include "gpu/command_buffer/service/mailbox_manager.h"
15 #include "gpu/command_buffer/service/memory_tracking.h"
16 #include "gpu/command_buffer/service/stream_texture_manager.h"
17
18 namespace gpu {
19 namespace gles2 {
20
21 static size_t GLTargetToFaceIndex(GLenum target) {
22   switch (target) {
23     case GL_TEXTURE_2D:
24     case GL_TEXTURE_EXTERNAL_OES:
25     case GL_TEXTURE_RECTANGLE_ARB:
26       return 0;
27     case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
28       return 0;
29     case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
30       return 1;
31     case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
32       return 2;
33     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
34       return 3;
35     case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
36       return 4;
37     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
38       return 5;
39     default:
40       NOTREACHED();
41       return 0;
42   }
43 }
44
45 static size_t FaceIndexToGLTarget(size_t index) {
46   switch (index) {
47     case 0:
48       return GL_TEXTURE_CUBE_MAP_POSITIVE_X;
49     case 1:
50       return GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
51     case 2:
52       return GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
53     case 3:
54       return GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
55     case 4:
56       return GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
57     case 5:
58       return GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
59     default:
60       NOTREACHED();
61       return 0;
62   }
63 }
64
65 TextureManager::DestructionObserver::DestructionObserver() {}
66
67 TextureManager::DestructionObserver::~DestructionObserver() {}
68
69 TextureManager::~TextureManager() {
70   FOR_EACH_OBSERVER(DestructionObserver,
71                     destruction_observers_,
72                     OnTextureManagerDestroying(this));
73
74   DCHECK(textures_.empty());
75
76   // If this triggers, that means something is keeping a reference to
77   // a Texture belonging to this.
78   CHECK_EQ(texture_count_, 0u);
79
80   DCHECK_EQ(0, num_unrenderable_textures_);
81   DCHECK_EQ(0, num_unsafe_textures_);
82   DCHECK_EQ(0, num_uncleared_mips_);
83   DCHECK_EQ(0, num_images_);
84 }
85
86 void TextureManager::Destroy(bool have_context) {
87   have_context_ = have_context;
88   textures_.clear();
89   for (int ii = 0; ii < kNumDefaultTextures; ++ii) {
90     default_textures_[ii] = NULL;
91   }
92
93   if (have_context) {
94     glDeleteTextures(arraysize(black_texture_ids_), black_texture_ids_);
95   }
96
97   DCHECK_EQ(0u, memory_tracker_managed_->GetMemRepresented());
98   DCHECK_EQ(0u, memory_tracker_unmanaged_->GetMemRepresented());
99 }
100
101 Texture::Texture(GLuint service_id)
102     : mailbox_manager_(NULL),
103       memory_tracking_ref_(NULL),
104       service_id_(service_id),
105       cleared_(true),
106       num_uncleared_mips_(0),
107       target_(0),
108       min_filter_(GL_NEAREST_MIPMAP_LINEAR),
109       mag_filter_(GL_LINEAR),
110       wrap_s_(GL_REPEAT),
111       wrap_t_(GL_REPEAT),
112       usage_(GL_NONE),
113       pool_(GL_TEXTURE_POOL_UNMANAGED_CHROMIUM),
114       max_level_set_(-1),
115       texture_complete_(false),
116       cube_complete_(false),
117       npot_(false),
118       has_been_bound_(false),
119       framebuffer_attachment_count_(0),
120       stream_texture_(false),
121       immutable_(false),
122       has_images_(false),
123       estimated_size_(0),
124       can_render_condition_(CAN_RENDER_ALWAYS) {
125 }
126
127 Texture::~Texture() {
128   if (mailbox_manager_)
129     mailbox_manager_->TextureDeleted(this);
130 }
131
132 void Texture::AddTextureRef(TextureRef* ref) {
133   DCHECK(refs_.find(ref) == refs_.end());
134   refs_.insert(ref);
135   if (!memory_tracking_ref_) {
136     memory_tracking_ref_ = ref;
137     GetMemTracker()->TrackMemAlloc(estimated_size());
138   }
139 }
140
141 void Texture::RemoveTextureRef(TextureRef* ref, bool have_context) {
142   if (memory_tracking_ref_ == ref) {
143     GetMemTracker()->TrackMemFree(estimated_size());
144     memory_tracking_ref_ = NULL;
145   }
146   size_t result = refs_.erase(ref);
147   DCHECK_EQ(result, 1u);
148   if (refs_.empty()) {
149     if (have_context) {
150       GLuint id = service_id();
151       glDeleteTextures(1, &id);
152     }
153     delete this;
154   } else if (memory_tracking_ref_ == NULL) {
155     // TODO(piman): tune ownership semantics for cross-context group shared
156     // textures.
157     memory_tracking_ref_ = *refs_.begin();
158     GetMemTracker()->TrackMemAlloc(estimated_size());
159   }
160 }
161
162 MemoryTypeTracker* Texture::GetMemTracker() {
163   DCHECK(memory_tracking_ref_);
164   return memory_tracking_ref_->manager()->GetMemTracker(pool_);
165 }
166
167 Texture::LevelInfo::LevelInfo()
168     : cleared(true),
169       target(0),
170       level(-1),
171       internal_format(0),
172       width(0),
173       height(0),
174       depth(0),
175       border(0),
176       format(0),
177       type(0),
178       estimated_size(0) {
179 }
180
181 Texture::LevelInfo::LevelInfo(const LevelInfo& rhs)
182     : cleared(rhs.cleared),
183       target(rhs.target),
184       level(rhs.level),
185       internal_format(rhs.internal_format),
186       width(rhs.width),
187       height(rhs.height),
188       depth(rhs.depth),
189       border(rhs.border),
190       format(rhs.format),
191       type(rhs.type),
192       image(rhs.image),
193       estimated_size(rhs.estimated_size) {
194 }
195
196 Texture::LevelInfo::~LevelInfo() {
197 }
198
199 Texture::CanRenderCondition Texture::GetCanRenderCondition() const {
200   if (target_ == 0)
201     return CAN_RENDER_ALWAYS;
202
203   if (target_ != GL_TEXTURE_EXTERNAL_OES) {
204     if (level_infos_.empty()) {
205       return CAN_RENDER_NEVER;
206     }
207
208     const Texture::LevelInfo& first_face = level_infos_[0][0];
209     if (first_face.width == 0 ||
210         first_face.height == 0 ||
211         first_face.depth == 0) {
212       return CAN_RENDER_NEVER;
213     }
214   }
215
216   bool needs_mips = NeedsMips();
217   if (needs_mips) {
218     if (!texture_complete())
219       return CAN_RENDER_NEVER;
220     if (target_ == GL_TEXTURE_CUBE_MAP && !cube_complete())
221       return CAN_RENDER_NEVER;
222   }
223
224   bool is_npot_compatible = !needs_mips &&
225       wrap_s_ == GL_CLAMP_TO_EDGE &&
226       wrap_t_ == GL_CLAMP_TO_EDGE;
227
228   if (!is_npot_compatible) {
229     if (target_ == GL_TEXTURE_RECTANGLE_ARB)
230       return CAN_RENDER_NEVER;
231     else if (npot())
232       return CAN_RENDER_ONLY_IF_NPOT;
233   }
234
235   return CAN_RENDER_ALWAYS;
236 }
237
238 bool Texture::CanRender(const FeatureInfo* feature_info) const {
239   switch (can_render_condition_) {
240     case CAN_RENDER_ALWAYS:
241       return true;
242     case CAN_RENDER_NEVER:
243       return false;
244     case CAN_RENDER_ONLY_IF_NPOT:
245       break;
246   }
247   return feature_info->feature_flags().npot_ok;
248 }
249
250 void Texture::AddToSignature(
251     const FeatureInfo* feature_info,
252     GLenum target,
253     GLint level,
254     std::string* signature) const {
255   DCHECK(feature_info);
256   DCHECK(signature);
257   DCHECK_GE(level, 0);
258   DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)),
259             level_infos_.size());
260   DCHECK_LT(static_cast<size_t>(level),
261             level_infos_[GLTargetToFaceIndex(target)].size());
262   const Texture::LevelInfo& info =
263       level_infos_[GLTargetToFaceIndex(target)][level];
264   *signature += base::StringPrintf(
265       "|Texture|target=%04x|level=%d|internal_format=%04x"
266       "|width=%d|height=%d|depth=%d|border=%d|format=%04x|type=%04x"
267       "|image=%d|canrender=%d|canrenderto=%d|npot_=%d"
268       "|min_filter=%04x|mag_filter=%04x|wrap_s=%04x|wrap_t=%04x"
269       "|usage=%04x",
270       target, level, info.internal_format,
271       info.width, info.height, info.depth, info.border,
272       info.format, info.type, info.image.get() != NULL,
273       CanRender(feature_info), CanRenderTo(), npot_,
274       min_filter_, mag_filter_, wrap_s_, wrap_t_,
275       usage_);
276 }
277
278 void Texture::SetMailboxManager(MailboxManager* mailbox_manager) {
279   DCHECK(!mailbox_manager_ || mailbox_manager_ == mailbox_manager);
280   mailbox_manager_ = mailbox_manager;
281 }
282
283 bool Texture::MarkMipmapsGenerated(
284     const FeatureInfo* feature_info) {
285   if (!CanGenerateMipmaps(feature_info)) {
286     return false;
287   }
288   for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
289     const Texture::LevelInfo& info1 = level_infos_[ii][0];
290     GLsizei width = info1.width;
291     GLsizei height = info1.height;
292     GLsizei depth = info1.depth;
293     GLenum target = target_ == GL_TEXTURE_2D ? GL_TEXTURE_2D :
294                                FaceIndexToGLTarget(ii);
295     int num_mips =
296         TextureManager::ComputeMipMapCount(target_, width, height, depth);
297     for (int level = 1; level < num_mips; ++level) {
298       width = std::max(1, width >> 1);
299       height = std::max(1, height >> 1);
300       depth = std::max(1, depth >> 1);
301       SetLevelInfo(feature_info,
302                    target,
303                    level,
304                    info1.internal_format,
305                    width,
306                    height,
307                    depth,
308                    info1.border,
309                    info1.format,
310                    info1.type,
311                    true);
312     }
313   }
314
315   return true;
316 }
317
318 void Texture::SetTarget(
319     const FeatureInfo* feature_info, GLenum target, GLint max_levels) {
320   DCHECK_EQ(0u, target_);  // you can only set this once.
321   target_ = target;
322   size_t num_faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
323   level_infos_.resize(num_faces);
324   for (size_t ii = 0; ii < num_faces; ++ii) {
325     level_infos_[ii].resize(max_levels);
326   }
327
328   if (target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ARB) {
329     min_filter_ = GL_LINEAR;
330     wrap_s_ = wrap_t_ = GL_CLAMP_TO_EDGE;
331   }
332
333   if (target == GL_TEXTURE_EXTERNAL_OES) {
334     immutable_ = true;
335   }
336   Update(feature_info);
337   UpdateCanRenderCondition();
338 }
339
340 bool Texture::CanGenerateMipmaps(
341     const FeatureInfo* feature_info) const {
342   if ((npot() && !feature_info->feature_flags().npot_ok) ||
343       level_infos_.empty() ||
344       target_ == GL_TEXTURE_EXTERNAL_OES ||
345       target_ == GL_TEXTURE_RECTANGLE_ARB) {
346     return false;
347   }
348
349   // Can't generate mips for depth or stencil textures.
350   const Texture::LevelInfo& first = level_infos_[0][0];
351   uint32 channels = GLES2Util::GetChannelsForFormat(first.format);
352   if (channels & (GLES2Util::kDepth | GLES2Util::kStencil)) {
353     return false;
354   }
355
356   // TODO(gman): Check internal_format, format and type.
357   for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
358     const LevelInfo& info = level_infos_[ii][0];
359     if ((info.target == 0) || (info.width != first.width) ||
360         (info.height != first.height) || (info.depth != 1) ||
361         (info.format != first.format) ||
362         (info.internal_format != first.internal_format) ||
363         (info.type != first.type) ||
364         feature_info->validators()->compressed_texture_format.IsValid(
365             info.internal_format) ||
366         info.image.get()) {
367       return false;
368     }
369   }
370   return true;
371 }
372
373 void Texture::SetLevelCleared(GLenum target, GLint level, bool cleared) {
374   DCHECK_GE(level, 0);
375   DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)),
376             level_infos_.size());
377   DCHECK_LT(static_cast<size_t>(level),
378             level_infos_[GLTargetToFaceIndex(target)].size());
379   Texture::LevelInfo& info =
380       level_infos_[GLTargetToFaceIndex(target)][level];
381   UpdateMipCleared(&info, cleared);
382   UpdateCleared();
383 }
384
385 void Texture::UpdateCleared() {
386   if (level_infos_.empty()) {
387     return;
388   }
389
390   const Texture::LevelInfo& first_face = level_infos_[0][0];
391   int levels_needed = TextureManager::ComputeMipMapCount(
392       target_, first_face.width, first_face.height, first_face.depth);
393   bool cleared = true;
394   for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
395     for (GLint jj = 0; jj < levels_needed; ++jj) {
396       const Texture::LevelInfo& info = level_infos_[ii][jj];
397       if (info.width > 0 && info.height > 0 && info.depth > 0 &&
398           !info.cleared) {
399         cleared = false;
400         break;
401       }
402     }
403   }
404   UpdateSafeToRenderFrom(cleared);
405 }
406
407 void Texture::UpdateSafeToRenderFrom(bool cleared) {
408   if (cleared_ == cleared)
409     return;
410   cleared_ = cleared;
411   int delta = cleared ? -1 : +1;
412   for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
413     (*it)->manager()->UpdateSafeToRenderFrom(delta);
414 }
415
416 void Texture::UpdateMipCleared(LevelInfo* info, bool cleared) {
417   if (info->cleared == cleared)
418     return;
419   info->cleared = cleared;
420   int delta = cleared ? -1 : +1;
421   num_uncleared_mips_ += delta;
422   for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
423     (*it)->manager()->UpdateUnclearedMips(delta);
424 }
425
426 void Texture::UpdateCanRenderCondition() {
427   CanRenderCondition can_render_condition = GetCanRenderCondition();
428   if (can_render_condition_ == can_render_condition)
429     return;
430   for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
431     (*it)->manager()->UpdateCanRenderCondition(can_render_condition_,
432                                                can_render_condition);
433   can_render_condition_ = can_render_condition;
434 }
435
436 void Texture::UpdateHasImages() {
437   if (level_infos_.empty())
438     return;
439
440   bool has_images = false;
441   for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
442     for (size_t jj = 0; jj < level_infos_[ii].size(); ++jj) {
443       const Texture::LevelInfo& info = level_infos_[ii][jj];
444       if (info.image.get() != NULL) {
445         has_images = true;
446         break;
447       }
448     }
449   }
450
451   if (has_images_ == has_images)
452     return;
453   has_images_ = has_images;
454   int delta = has_images ? +1 : -1;
455   for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
456     (*it)->manager()->UpdateNumImages(delta);
457 }
458
459 void Texture::IncAllFramebufferStateChangeCount() {
460   for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
461     (*it)->manager()->IncFramebufferStateChangeCount();
462 }
463
464 void Texture::SetLevelInfo(
465     const FeatureInfo* feature_info,
466     GLenum target,
467     GLint level,
468     GLenum internal_format,
469     GLsizei width,
470     GLsizei height,
471     GLsizei depth,
472     GLint border,
473     GLenum format,
474     GLenum type,
475     bool cleared) {
476   DCHECK_GE(level, 0);
477   DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)),
478             level_infos_.size());
479   DCHECK_LT(static_cast<size_t>(level),
480             level_infos_[GLTargetToFaceIndex(target)].size());
481   DCHECK_GE(width, 0);
482   DCHECK_GE(height, 0);
483   DCHECK_GE(depth, 0);
484   Texture::LevelInfo& info =
485       level_infos_[GLTargetToFaceIndex(target)][level];
486   info.target = target;
487   info.level = level;
488   info.internal_format = internal_format;
489   info.width = width;
490   info.height = height;
491   info.depth = depth;
492   info.border = border;
493   info.format = format;
494   info.type = type;
495   info.image = 0;
496
497   estimated_size_ -= info.estimated_size;
498   GLES2Util::ComputeImageDataSizes(
499       width, height, format, type, 4, &info.estimated_size, NULL, NULL);
500   estimated_size_ += info.estimated_size;
501
502   UpdateMipCleared(&info, cleared);
503   max_level_set_ = std::max(max_level_set_, level);
504   Update(feature_info);
505   UpdateCleared();
506   UpdateCanRenderCondition();
507   UpdateHasImages();
508   if (IsAttachedToFramebuffer()) {
509     // TODO(gman): If textures tracked which framebuffers they were attached to
510     // we could just mark those framebuffers as not complete.
511     IncAllFramebufferStateChangeCount();
512   }
513 }
514
515 bool Texture::ValidForTexture(
516     GLint target,
517     GLint level,
518     GLint xoffset,
519     GLint yoffset,
520     GLsizei width,
521     GLsizei height,
522     GLenum format,
523     GLenum type) const {
524   size_t face_index = GLTargetToFaceIndex(target);
525   if (level >= 0 && face_index < level_infos_.size() &&
526       static_cast<size_t>(level) < level_infos_[face_index].size()) {
527     const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level];
528     int32 right;
529     int32 top;
530     return SafeAddInt32(xoffset, width, &right) &&
531            SafeAddInt32(yoffset, height, &top) &&
532            xoffset >= 0 &&
533            yoffset >= 0 &&
534            right <= info.width &&
535            top <= info.height &&
536            format == info.internal_format &&
537            type == info.type;
538   }
539   return false;
540 }
541
542 bool Texture::GetLevelSize(
543     GLint target, GLint level, GLsizei* width, GLsizei* height) const {
544   DCHECK(width);
545   DCHECK(height);
546   size_t face_index = GLTargetToFaceIndex(target);
547   if (level >= 0 && face_index < level_infos_.size() &&
548       static_cast<size_t>(level) < level_infos_[face_index].size()) {
549     const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level];
550     if (info.target != 0) {
551       *width = info.width;
552       *height = info.height;
553       return true;
554     }
555   }
556   return false;
557 }
558
559 bool Texture::GetLevelType(
560     GLint target, GLint level, GLenum* type, GLenum* internal_format) const {
561   DCHECK(type);
562   DCHECK(internal_format);
563   size_t face_index = GLTargetToFaceIndex(target);
564   if (level >= 0 && face_index < level_infos_.size() &&
565       static_cast<size_t>(level) < level_infos_[face_index].size()) {
566     const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level];
567     if (info.target != 0) {
568       *type = info.type;
569       *internal_format = info.internal_format;
570       return true;
571     }
572   }
573   return false;
574 }
575
576 GLenum Texture::SetParameter(
577     const FeatureInfo* feature_info, GLenum pname, GLint param) {
578   DCHECK(feature_info);
579
580   if (target_ == GL_TEXTURE_EXTERNAL_OES ||
581       target_ == GL_TEXTURE_RECTANGLE_ARB) {
582     if (pname == GL_TEXTURE_MIN_FILTER &&
583         (param != GL_NEAREST && param != GL_LINEAR))
584       return GL_INVALID_ENUM;
585     if ((pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T) &&
586         param != GL_CLAMP_TO_EDGE)
587       return GL_INVALID_ENUM;
588   }
589
590   switch (pname) {
591     case GL_TEXTURE_MIN_FILTER:
592       if (!feature_info->validators()->texture_min_filter_mode.IsValid(param)) {
593         return GL_INVALID_ENUM;
594       }
595       min_filter_ = param;
596       break;
597     case GL_TEXTURE_MAG_FILTER:
598       if (!feature_info->validators()->texture_mag_filter_mode.IsValid(param)) {
599         return GL_INVALID_ENUM;
600       }
601       mag_filter_ = param;
602       break;
603     case GL_TEXTURE_POOL_CHROMIUM:
604       if (!feature_info->validators()->texture_pool.IsValid(param)) {
605         return GL_INVALID_ENUM;
606       }
607       GetMemTracker()->TrackMemFree(estimated_size());
608       pool_ = param;
609       GetMemTracker()->TrackMemAlloc(estimated_size());
610       break;
611     case GL_TEXTURE_WRAP_S:
612       if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) {
613         return GL_INVALID_ENUM;
614       }
615       wrap_s_ = param;
616       break;
617     case GL_TEXTURE_WRAP_T:
618       if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) {
619         return GL_INVALID_ENUM;
620       }
621       wrap_t_ = param;
622       break;
623     case GL_TEXTURE_MAX_ANISOTROPY_EXT:
624       if (param < 1) {
625         return GL_INVALID_VALUE;
626       }
627       break;
628     case GL_TEXTURE_USAGE_ANGLE:
629       if (!feature_info->validators()->texture_usage.IsValid(param)) {
630         return GL_INVALID_ENUM;
631       }
632       usage_ = param;
633       break;
634     default:
635       NOTREACHED();
636       return GL_INVALID_ENUM;
637   }
638   Update(feature_info);
639   UpdateCleared();
640   UpdateCanRenderCondition();
641   return GL_NO_ERROR;
642 }
643
644 void Texture::Update(const FeatureInfo* feature_info) {
645   // Update npot status.
646   // Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others
647   npot_ = target_ == GL_TEXTURE_EXTERNAL_OES;
648
649   if (level_infos_.empty()) {
650     texture_complete_ = false;
651     cube_complete_ = false;
652     return;
653   }
654
655   // checks that the first mip of any face is npot.
656   for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
657     const Texture::LevelInfo& info = level_infos_[ii][0];
658     if (GLES2Util::IsNPOT(info.width) ||
659         GLES2Util::IsNPOT(info.height) ||
660         GLES2Util::IsNPOT(info.depth)) {
661       npot_ = true;
662       break;
663     }
664   }
665
666   // Update texture_complete and cube_complete status.
667   const Texture::LevelInfo& first_face = level_infos_[0][0];
668   int levels_needed = TextureManager::ComputeMipMapCount(
669       target_, first_face.width, first_face.height, first_face.depth);
670   texture_complete_ =
671       max_level_set_ >= (levels_needed - 1) && max_level_set_ >= 0;
672   cube_complete_ = (level_infos_.size() == 6) &&
673                    (first_face.width == first_face.height);
674
675   if (first_face.width == 0 || first_face.height == 0) {
676     texture_complete_ = false;
677   }
678   if (first_face.type == GL_FLOAT &&
679       !feature_info->feature_flags().enable_texture_float_linear &&
680       (min_filter_ != GL_NEAREST_MIPMAP_NEAREST ||
681        mag_filter_ != GL_NEAREST)) {
682     texture_complete_ = false;
683   } else if (first_face.type == GL_HALF_FLOAT_OES &&
684              !feature_info->feature_flags().enable_texture_half_float_linear &&
685              (min_filter_ != GL_NEAREST_MIPMAP_NEAREST ||
686               mag_filter_ != GL_NEAREST)) {
687     texture_complete_ = false;
688   }
689   for (size_t ii = 0;
690        ii < level_infos_.size() && (cube_complete_ || texture_complete_);
691        ++ii) {
692     const Texture::LevelInfo& level0 = level_infos_[ii][0];
693     if (level0.target == 0 ||
694         level0.width != first_face.width ||
695         level0.height != first_face.height ||
696         level0.depth != 1 ||
697         level0.internal_format != first_face.internal_format ||
698         level0.format != first_face.format ||
699         level0.type != first_face.type) {
700       cube_complete_ = false;
701     }
702     // Get level0 dimensions
703     GLsizei width = level0.width;
704     GLsizei height = level0.height;
705     GLsizei depth = level0.depth;
706     for (GLint jj = 1; jj < levels_needed; ++jj) {
707       // compute required size for mip.
708       width = std::max(1, width >> 1);
709       height = std::max(1, height >> 1);
710       depth = std::max(1, depth >> 1);
711       const Texture::LevelInfo& info = level_infos_[ii][jj];
712       if (info.target == 0 ||
713           info.width != width ||
714           info.height != height ||
715           info.depth != depth ||
716           info.internal_format != level0.internal_format ||
717           info.format != level0.format ||
718           info.type != level0.type) {
719         texture_complete_ = false;
720         break;
721       }
722     }
723   }
724 }
725
726 bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) {
727   DCHECK(decoder);
728   if (cleared_) {
729     return true;
730   }
731
732   const Texture::LevelInfo& first_face = level_infos_[0][0];
733   int levels_needed = TextureManager::ComputeMipMapCount(
734       target_, first_face.width, first_face.height, first_face.depth);
735
736   for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
737     for (GLint jj = 0; jj < levels_needed; ++jj) {
738       Texture::LevelInfo& info = level_infos_[ii][jj];
739       if (info.target != 0) {
740         if (!ClearLevel(decoder, info.target, jj)) {
741           return false;
742         }
743       }
744     }
745   }
746   UpdateSafeToRenderFrom(true);
747   return true;
748 }
749
750 bool Texture::IsLevelCleared(GLenum target, GLint level) const {
751   size_t face_index = GLTargetToFaceIndex(target);
752   if (face_index >= level_infos_.size() ||
753       level >= static_cast<GLint>(level_infos_[face_index].size())) {
754     return true;
755   }
756
757   const Texture::LevelInfo& info = level_infos_[face_index][level];
758
759   return info.cleared;
760 }
761
762 bool Texture::ClearLevel(
763     GLES2Decoder* decoder, GLenum target, GLint level) {
764   DCHECK(decoder);
765   size_t face_index = GLTargetToFaceIndex(target);
766   if (face_index >= level_infos_.size() ||
767       level >= static_cast<GLint>(level_infos_[face_index].size())) {
768     return true;
769   }
770
771   Texture::LevelInfo& info = level_infos_[face_index][level];
772
773   DCHECK(target == info.target);
774
775   if (info.target == 0 ||
776       info.cleared ||
777       info.width == 0 ||
778       info.height == 0 ||
779       info.depth == 0) {
780     return true;
781   }
782
783   // NOTE: It seems kind of gross to call back into the decoder for this
784   // but only the decoder knows all the state (like unpack_alignment_) that's
785   // needed to be able to call GL correctly.
786   bool cleared = decoder->ClearLevel(
787       service_id_, target_, info.target, info.level, info.format, info.type,
788       info.width, info.height, immutable_);
789   UpdateMipCleared(&info, cleared);
790   return info.cleared;
791 }
792
793 void Texture::SetLevelImage(
794     const FeatureInfo* feature_info,
795     GLenum target,
796     GLint level,
797     gfx::GLImage* image) {
798   DCHECK_GE(level, 0);
799   DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)),
800             level_infos_.size());
801   DCHECK_LT(static_cast<size_t>(level),
802             level_infos_[GLTargetToFaceIndex(target)].size());
803   Texture::LevelInfo& info =
804       level_infos_[GLTargetToFaceIndex(target)][level];
805   DCHECK_EQ(info.target, target);
806   DCHECK_EQ(info.level, level);
807   info.image = image;
808   UpdateCanRenderCondition();
809   UpdateHasImages();
810 }
811
812 gfx::GLImage* Texture::GetLevelImage(GLint target, GLint level) const {
813   size_t face_index = GLTargetToFaceIndex(target);
814   if (level >= 0 && face_index < level_infos_.size() &&
815       static_cast<size_t>(level) < level_infos_[face_index].size()) {
816     const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level];
817     if (info.target != 0) {
818       return info.image.get();
819     }
820   }
821   return 0;
822 }
823
824
825 TextureRef::TextureRef(TextureManager* manager,
826                        GLuint client_id,
827                        Texture* texture)
828     : manager_(manager),
829       texture_(texture),
830       client_id_(client_id),
831       is_stream_texture_owner_(false) {
832   DCHECK(manager_);
833   DCHECK(texture_);
834   texture_->AddTextureRef(this);
835   manager_->StartTracking(this);
836 }
837
838 scoped_refptr<TextureRef> TextureRef::Create(TextureManager* manager,
839                                              GLuint client_id,
840                                              GLuint service_id) {
841   return new TextureRef(manager, client_id, new Texture(service_id));
842 }
843
844 TextureRef::~TextureRef() {
845   manager_->StopTracking(this);
846   texture_->RemoveTextureRef(this, manager_->have_context_);
847   manager_ = NULL;
848 }
849
850 TextureManager::TextureManager(MemoryTracker* memory_tracker,
851                                FeatureInfo* feature_info,
852                                GLint max_texture_size,
853                                GLint max_cube_map_texture_size)
854     : memory_tracker_managed_(new MemoryTypeTracker(memory_tracker,
855                                                     MemoryTracker::kManaged)),
856       memory_tracker_unmanaged_(
857           new MemoryTypeTracker(memory_tracker, MemoryTracker::kUnmanaged)),
858       feature_info_(feature_info),
859       framebuffer_manager_(NULL),
860       stream_texture_manager_(NULL),
861       max_texture_size_(max_texture_size),
862       max_cube_map_texture_size_(max_cube_map_texture_size),
863       max_levels_(ComputeMipMapCount(GL_TEXTURE_2D,
864                                      max_texture_size,
865                                      max_texture_size,
866                                      max_texture_size)),
867       max_cube_map_levels_(ComputeMipMapCount(GL_TEXTURE_CUBE_MAP,
868                                               max_cube_map_texture_size,
869                                               max_cube_map_texture_size,
870                                               max_cube_map_texture_size)),
871       num_unrenderable_textures_(0),
872       num_unsafe_textures_(0),
873       num_uncleared_mips_(0),
874       num_images_(0),
875       texture_count_(0),
876       have_context_(true) {
877   for (int ii = 0; ii < kNumDefaultTextures; ++ii) {
878     black_texture_ids_[ii] = 0;
879   }
880 }
881
882 bool TextureManager::Initialize() {
883   // TODO(gman): The default textures have to be real textures, not the 0
884   // texture because we simulate non shared resources on top of shared
885   // resources and all contexts that share resource share the same default
886   // texture.
887   default_textures_[kTexture2D] = CreateDefaultAndBlackTextures(
888       GL_TEXTURE_2D, &black_texture_ids_[kTexture2D]);
889   default_textures_[kCubeMap] = CreateDefaultAndBlackTextures(
890       GL_TEXTURE_CUBE_MAP, &black_texture_ids_[kCubeMap]);
891
892   if (feature_info_->feature_flags().oes_egl_image_external) {
893     default_textures_[kExternalOES] = CreateDefaultAndBlackTextures(
894         GL_TEXTURE_EXTERNAL_OES, &black_texture_ids_[kExternalOES]);
895   }
896
897   if (feature_info_->feature_flags().arb_texture_rectangle) {
898     default_textures_[kRectangleARB] = CreateDefaultAndBlackTextures(
899         GL_TEXTURE_RECTANGLE_ARB, &black_texture_ids_[kRectangleARB]);
900   }
901
902   return true;
903 }
904
905 scoped_refptr<TextureRef>
906     TextureManager::CreateDefaultAndBlackTextures(
907         GLenum target,
908         GLuint* black_texture) {
909   static uint8 black[] = {0, 0, 0, 255};
910
911   // Sampling a texture not associated with any EGLImage sibling will return
912   // black values according to the spec.
913   bool needs_initialization = (target != GL_TEXTURE_EXTERNAL_OES);
914   bool needs_faces = (target == GL_TEXTURE_CUBE_MAP);
915
916   // Make default textures and texture for replacing non-renderable textures.
917   GLuint ids[2];
918   glGenTextures(arraysize(ids), ids);
919   for (unsigned long ii = 0; ii < arraysize(ids); ++ii) {
920     glBindTexture(target, ids[ii]);
921     if (needs_initialization) {
922       if (needs_faces) {
923         for (int jj = 0; jj < GLES2Util::kNumFaces; ++jj) {
924           glTexImage2D(GLES2Util::IndexToGLFaceTarget(jj), 0, GL_RGBA, 1, 1, 0,
925                        GL_RGBA, GL_UNSIGNED_BYTE, black);
926         }
927       } else {
928         glTexImage2D(target, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
929                      GL_UNSIGNED_BYTE, black);
930       }
931     }
932   }
933   glBindTexture(target, 0);
934
935   scoped_refptr<TextureRef> default_texture(
936       TextureRef::Create(this, 0, ids[1]));
937   SetTarget(default_texture.get(), target);
938   if (needs_faces) {
939     for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) {
940       SetLevelInfo(default_texture.get(),
941                    GLES2Util::IndexToGLFaceTarget(ii),
942                    0,
943                    GL_RGBA,
944                    1,
945                    1,
946                    1,
947                    0,
948                    GL_RGBA,
949                    GL_UNSIGNED_BYTE,
950                    true);
951     }
952   } else {
953     if (needs_initialization) {
954       SetLevelInfo(default_texture.get(),
955                    GL_TEXTURE_2D,
956                    0,
957                    GL_RGBA,
958                    1,
959                    1,
960                    1,
961                    0,
962                    GL_RGBA,
963                    GL_UNSIGNED_BYTE,
964                    true);
965     } else {
966       SetLevelInfo(default_texture.get(),
967                    GL_TEXTURE_EXTERNAL_OES,
968                    0,
969                    GL_RGBA,
970                    1,
971                    1,
972                    1,
973                    0,
974                    GL_RGBA,
975                    GL_UNSIGNED_BYTE,
976                    true);
977     }
978   }
979
980   *black_texture = ids[0];
981   return default_texture;
982 }
983
984 bool TextureManager::ValidForTarget(
985     GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth) {
986   GLsizei max_size = MaxSizeForTarget(target) >> level;
987   return level >= 0 &&
988          width >= 0 &&
989          height >= 0 &&
990          depth >= 0 &&
991          level < MaxLevelsForTarget(target) &&
992          width <= max_size &&
993          height <= max_size &&
994          depth <= max_size &&
995          (level == 0 || feature_info_->feature_flags().npot_ok ||
996           (!GLES2Util::IsNPOT(width) &&
997            !GLES2Util::IsNPOT(height) &&
998            !GLES2Util::IsNPOT(depth))) &&
999          (target != GL_TEXTURE_CUBE_MAP || (width == height && depth == 1)) &&
1000          (target != GL_TEXTURE_2D || (depth == 1));
1001 }
1002
1003 void TextureManager::SetTarget(TextureRef* ref, GLenum target) {
1004   DCHECK(ref);
1005   ref->texture()
1006       ->SetTarget(feature_info_.get(), target, MaxLevelsForTarget(target));
1007 }
1008
1009 void TextureManager::SetStreamTexture(TextureRef* ref, bool stream_texture) {
1010   DCHECK(ref);
1011   // Only the owner can mark as non-stream texture.
1012   DCHECK_EQ(stream_texture, !ref->is_stream_texture_owner_);
1013   ref->texture()->SetStreamTexture(stream_texture);
1014   ref->set_is_stream_texture_owner(stream_texture);
1015 }
1016
1017 bool TextureManager::IsStreamTextureOwner(TextureRef* ref) {
1018   DCHECK(ref);
1019   return ref->is_stream_texture_owner();
1020 }
1021
1022 void TextureManager::SetLevelCleared(TextureRef* ref,
1023                                      GLenum target,
1024                                      GLint level,
1025                                      bool cleared) {
1026   DCHECK(ref);
1027   ref->texture()->SetLevelCleared(target, level, cleared);
1028 }
1029
1030 bool TextureManager::ClearRenderableLevels(
1031     GLES2Decoder* decoder, TextureRef* ref) {
1032   DCHECK(ref);
1033   return ref->texture()->ClearRenderableLevels(decoder);
1034 }
1035
1036 bool TextureManager::ClearTextureLevel(
1037     GLES2Decoder* decoder, TextureRef* ref,
1038     GLenum target, GLint level) {
1039   DCHECK(ref);
1040   Texture* texture = ref->texture();
1041   if (texture->num_uncleared_mips() == 0) {
1042     return true;
1043   }
1044   bool result = texture->ClearLevel(decoder, target, level);
1045   texture->UpdateCleared();
1046   return result;
1047 }
1048
1049 void TextureManager::SetLevelInfo(
1050     TextureRef* ref,
1051     GLenum target,
1052     GLint level,
1053     GLenum internal_format,
1054     GLsizei width,
1055     GLsizei height,
1056     GLsizei depth,
1057     GLint border,
1058     GLenum format,
1059     GLenum type,
1060     bool cleared) {
1061   DCHECK(ref);
1062   Texture* texture = ref->texture();
1063
1064   texture->GetMemTracker()->TrackMemFree(texture->estimated_size());
1065   texture->SetLevelInfo(feature_info_.get(),
1066                         target,
1067                         level,
1068                         internal_format,
1069                         width,
1070                         height,
1071                         depth,
1072                         border,
1073                         format,
1074                         type,
1075                         cleared);
1076   texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size());
1077 }
1078
1079 Texture* TextureManager::Produce(TextureRef* ref) {
1080   DCHECK(ref);
1081   return ref->texture();
1082 }
1083
1084 TextureRef* TextureManager::Consume(
1085     GLuint client_id,
1086     Texture* texture) {
1087   DCHECK(client_id);
1088   scoped_refptr<TextureRef> ref(new TextureRef(this, client_id, texture));
1089   bool result = textures_.insert(std::make_pair(client_id, ref)).second;
1090   DCHECK(result);
1091   return ref.get();
1092 }
1093
1094 void TextureManager::SetParameter(
1095     const char* function_name, ErrorState* error_state,
1096     TextureRef* ref, GLenum pname, GLint param) {
1097   DCHECK(error_state);
1098   DCHECK(ref);
1099   Texture* texture = ref->texture();
1100   GLenum result = texture->SetParameter(feature_info_.get(), pname, param);
1101   if (result != GL_NO_ERROR) {
1102     if (result == GL_INVALID_ENUM) {
1103       ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1104           error_state, function_name, param, "param");
1105     } else {
1106       ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(
1107           error_state, result, function_name, pname, static_cast<GLint>(param));
1108     }
1109   } else {
1110     // Texture tracking pools exist only for the command decoder, so
1111     // do not pass them on to the native GL implementation.
1112     if (pname != GL_TEXTURE_POOL_CHROMIUM) {
1113       glTexParameteri(texture->target(), pname, param);
1114     }
1115   }
1116 }
1117
1118 bool TextureManager::MarkMipmapsGenerated(TextureRef* ref) {
1119   DCHECK(ref);
1120   Texture* texture = ref->texture();
1121   texture->GetMemTracker()->TrackMemFree(texture->estimated_size());
1122   bool result = texture->MarkMipmapsGenerated(feature_info_.get());
1123   texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size());
1124   return result;
1125 }
1126
1127 TextureRef* TextureManager::CreateTexture(
1128     GLuint client_id, GLuint service_id) {
1129   DCHECK_NE(0u, service_id);
1130   scoped_refptr<TextureRef> ref(TextureRef::Create(
1131       this, client_id, service_id));
1132   std::pair<TextureMap::iterator, bool> result =
1133       textures_.insert(std::make_pair(client_id, ref));
1134   DCHECK(result.second);
1135   return ref.get();
1136 }
1137
1138 TextureRef* TextureManager::GetTexture(
1139     GLuint client_id) const {
1140   TextureMap::const_iterator it = textures_.find(client_id);
1141   return it != textures_.end() ? it->second.get() : NULL;
1142 }
1143
1144 void TextureManager::RemoveTexture(GLuint client_id) {
1145   TextureMap::iterator it = textures_.find(client_id);
1146   if (it != textures_.end()) {
1147     it->second->reset_client_id();
1148     textures_.erase(it);
1149   }
1150 }
1151
1152 void TextureManager::StartTracking(TextureRef* ref) {
1153   Texture* texture = ref->texture();
1154   ++texture_count_;
1155   num_uncleared_mips_ += texture->num_uncleared_mips();
1156   if (!texture->SafeToRenderFrom())
1157     ++num_unsafe_textures_;
1158   if (!texture->CanRender(feature_info_.get()))
1159     ++num_unrenderable_textures_;
1160   if (texture->HasImages())
1161     ++num_images_;
1162 }
1163
1164 void TextureManager::StopTracking(TextureRef* ref) {
1165   FOR_EACH_OBSERVER(DestructionObserver,
1166                     destruction_observers_,
1167                     OnTextureRefDestroying(ref));
1168
1169   Texture* texture = ref->texture();
1170   if (ref->is_stream_texture_owner_ && stream_texture_manager_) {
1171     DCHECK(texture->IsStreamTexture());
1172     stream_texture_manager_->DestroyStreamTexture(texture->service_id());
1173   }
1174
1175   --texture_count_;
1176   if (texture->HasImages()) {
1177     DCHECK_NE(0, num_images_);
1178     --num_images_;
1179   }
1180   if (!texture->CanRender(feature_info_.get())) {
1181     DCHECK_NE(0, num_unrenderable_textures_);
1182     --num_unrenderable_textures_;
1183   }
1184   if (!texture->SafeToRenderFrom()) {
1185     DCHECK_NE(0, num_unsafe_textures_);
1186     --num_unsafe_textures_;
1187   }
1188   num_uncleared_mips_ -= texture->num_uncleared_mips();
1189   DCHECK_GE(num_uncleared_mips_, 0);
1190 }
1191
1192 MemoryTypeTracker* TextureManager::GetMemTracker(GLenum tracking_pool) {
1193   switch(tracking_pool) {
1194     case GL_TEXTURE_POOL_MANAGED_CHROMIUM:
1195       return memory_tracker_managed_.get();
1196       break;
1197     case GL_TEXTURE_POOL_UNMANAGED_CHROMIUM:
1198       return memory_tracker_unmanaged_.get();
1199       break;
1200     default:
1201       break;
1202   }
1203   NOTREACHED();
1204   return NULL;
1205 }
1206
1207 Texture* TextureManager::GetTextureForServiceId(GLuint service_id) const {
1208   // This doesn't need to be fast. It's only used during slow queries.
1209   for (TextureMap::const_iterator it = textures_.begin();
1210        it != textures_.end(); ++it) {
1211     Texture* texture = it->second->texture();
1212     if (texture->service_id() == service_id)
1213       return texture;
1214   }
1215   return NULL;
1216 }
1217
1218 GLsizei TextureManager::ComputeMipMapCount(GLenum target,
1219                                            GLsizei width,
1220                                            GLsizei height,
1221                                            GLsizei depth) {
1222   switch (target) {
1223     case GL_TEXTURE_EXTERNAL_OES:
1224       return 1;
1225     default:
1226       return 1 +
1227              base::bits::Log2Floor(std::max(std::max(width, height), depth));
1228   }
1229 }
1230
1231 void TextureManager::SetLevelImage(
1232     TextureRef* ref,
1233     GLenum target,
1234     GLint level,
1235     gfx::GLImage* image) {
1236   DCHECK(ref);
1237   ref->texture()->SetLevelImage(feature_info_.get(), target, level, image);
1238 }
1239
1240 void TextureManager::AddToSignature(
1241     TextureRef* ref,
1242     GLenum target,
1243     GLint level,
1244     std::string* signature) const {
1245   ref->texture()->AddToSignature(feature_info_.get(), target, level, signature);
1246 }
1247
1248 void TextureManager::UpdateSafeToRenderFrom(int delta) {
1249   num_unsafe_textures_ += delta;
1250   DCHECK_GE(num_unsafe_textures_, 0);
1251 }
1252
1253 void TextureManager::UpdateUnclearedMips(int delta) {
1254   num_uncleared_mips_ += delta;
1255   DCHECK_GE(num_uncleared_mips_, 0);
1256 }
1257
1258 void TextureManager::UpdateCanRenderCondition(
1259     Texture::CanRenderCondition old_condition,
1260     Texture::CanRenderCondition new_condition) {
1261   if (old_condition == Texture::CAN_RENDER_NEVER ||
1262       (old_condition == Texture::CAN_RENDER_ONLY_IF_NPOT &&
1263        !feature_info_->feature_flags().npot_ok)) {
1264     DCHECK_GT(num_unrenderable_textures_, 0);
1265     --num_unrenderable_textures_;
1266   }
1267   if (new_condition == Texture::CAN_RENDER_NEVER ||
1268       (new_condition == Texture::CAN_RENDER_ONLY_IF_NPOT &&
1269        !feature_info_->feature_flags().npot_ok))
1270     ++num_unrenderable_textures_;
1271 }
1272
1273 void TextureManager::UpdateNumImages(int delta) {
1274   num_images_ += delta;
1275   DCHECK_GE(num_images_, 0);
1276 }
1277
1278 void TextureManager::IncFramebufferStateChangeCount() {
1279   if (framebuffer_manager_)
1280     framebuffer_manager_->IncFramebufferStateChangeCount();
1281 }
1282
1283 bool TextureManager::ValidateTextureParameters(
1284     ErrorState* error_state, const char* function_name,
1285     GLenum target, GLenum format, GLenum type, GLint level) {
1286   if (!feature_info_->GetTextureFormatValidator(format).IsValid(type)) {
1287       ERRORSTATE_SET_GL_ERROR(
1288           error_state, GL_INVALID_OPERATION, function_name,
1289           (std::string("invalid type ") +
1290            GLES2Util::GetStringEnum(type) + " for format " +
1291            GLES2Util::GetStringEnum(format)).c_str());
1292       return false;
1293   }
1294
1295   uint32 channels = GLES2Util::GetChannelsForFormat(format);
1296   if ((channels & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && level) {
1297     ERRORSTATE_SET_GL_ERROR(
1298         error_state, GL_INVALID_OPERATION, function_name,
1299         (std::string("invalid type ") +
1300          GLES2Util::GetStringEnum(type) + " for format " +
1301          GLES2Util::GetStringEnum(format)).c_str());
1302     return false;
1303   }
1304   return true;
1305 }
1306
1307 // Gets the texture id for a given target.
1308 TextureRef* TextureManager::GetTextureInfoForTarget(
1309     ContextState* state, GLenum target) {
1310   TextureUnit& unit = state->texture_units[state->active_texture_unit];
1311   TextureRef* texture = NULL;
1312   switch (target) {
1313     case GL_TEXTURE_2D:
1314       texture = unit.bound_texture_2d.get();
1315       break;
1316     case GL_TEXTURE_CUBE_MAP:
1317     case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1318     case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1319     case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1320     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1321     case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1322     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1323       texture = unit.bound_texture_cube_map.get();
1324       break;
1325     case GL_TEXTURE_EXTERNAL_OES:
1326       texture = unit.bound_texture_external_oes.get();
1327       break;
1328     case GL_TEXTURE_RECTANGLE_ARB:
1329       texture = unit.bound_texture_rectangle_arb.get();
1330       break;
1331     default:
1332       NOTREACHED();
1333       return NULL;
1334   }
1335   return texture;
1336 }
1337
1338 TextureRef* TextureManager::GetTextureInfoForTargetUnlessDefault(
1339     ContextState* state, GLenum target) {
1340   TextureRef* texture = GetTextureInfoForTarget(state, target);
1341   if (!texture)
1342     return NULL;
1343   if (texture == GetDefaultTextureInfo(target))
1344     return NULL;
1345   return texture;
1346 }
1347
1348 bool TextureManager::ValidateTexImage2D(
1349     ContextState* state,
1350     const char* function_name,
1351     const DoTextImage2DArguments& args,
1352     TextureRef** texture_ref) {
1353   ErrorState* error_state = state->GetErrorState();
1354   const Validators* validators = feature_info_->validators();
1355   if (!validators->texture_target.IsValid(args.target)) {
1356     ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1357         error_state, function_name, args.target, "target");
1358     return false;
1359   }
1360   if (!validators->texture_format.IsValid(args.internal_format)) {
1361     ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1362         error_state, function_name, args.internal_format,
1363         "internal_format");
1364     return false;
1365   }
1366   if (!validators->texture_format.IsValid(args.format)) {
1367     ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1368         error_state, function_name, args.format, "format");
1369     return false;
1370   }
1371   if (!validators->pixel_type.IsValid(args.type)) {
1372     ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1373         error_state, function_name, args.type, "type");
1374     return false;
1375   }
1376   if (args.format != args.internal_format) {
1377     ERRORSTATE_SET_GL_ERROR(
1378         error_state, GL_INVALID_OPERATION, function_name,
1379         "format != internalFormat");
1380     return false;
1381   }
1382   if (!ValidateTextureParameters(
1383       error_state, function_name, args.target, args.format, args.type,
1384       args.level)) {
1385     return false;
1386   }
1387   if (!ValidForTarget(args.target, args.level, args.width, args.height, 1) ||
1388       args.border != 0) {
1389     ERRORSTATE_SET_GL_ERROR(
1390         error_state, GL_INVALID_VALUE, function_name,
1391         "dimensions out of range");
1392     return false;
1393   }
1394   if ((GLES2Util::GetChannelsForFormat(args.format) &
1395        (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && args.pixels) {
1396     ERRORSTATE_SET_GL_ERROR(
1397         error_state, GL_INVALID_OPERATION,
1398         function_name, "can not supply data for depth or stencil textures");
1399     return false;
1400   }
1401
1402   TextureRef* local_texture_ref = GetTextureInfoForTarget(state, args.target);
1403   if (!local_texture_ref) {
1404     ERRORSTATE_SET_GL_ERROR(
1405         error_state, GL_INVALID_OPERATION, function_name,
1406         "unknown texture for target");
1407     return false;
1408   }
1409   if (local_texture_ref->texture()->IsImmutable()) {
1410     ERRORSTATE_SET_GL_ERROR(
1411         error_state, GL_INVALID_OPERATION, function_name,
1412         "texture is immutable");
1413     return false;
1414   }
1415
1416   // TODO - verify that using the managed vs unmanaged does not matter.
1417   // They both use the same MemoryTracker, and this call just re-routes
1418   // to it.
1419   if (!memory_tracker_managed_->EnsureGPUMemoryAvailable(args.pixels_size)) {
1420     ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, "glTexImage2D",
1421                             "out of memory");
1422     return false;
1423   }
1424
1425   // Write the TextureReference since this is valid.
1426   *texture_ref = local_texture_ref;
1427   return true;
1428 }
1429
1430 void TextureManager::ValidateAndDoTexImage2D(
1431     DecoderTextureState* texture_state,
1432     ContextState* state,
1433     DecoderFramebufferState* framebuffer_state,
1434     const DoTextImage2DArguments& args) {
1435   TextureRef* texture_ref;
1436   if (!ValidateTexImage2D(state, "glTexImage2D", args, &texture_ref)) {
1437     return;
1438   }
1439
1440   DoTexImage2D(texture_state, state->GetErrorState(), framebuffer_state,
1441                texture_ref, args);
1442 }
1443
1444 void TextureManager::DoTexImage2D(
1445     DecoderTextureState* texture_state,
1446     ErrorState* error_state,
1447     DecoderFramebufferState* framebuffer_state,
1448     TextureRef* texture_ref,
1449     const DoTextImage2DArguments& args) {
1450   Texture* texture = texture_ref->texture();
1451   GLsizei tex_width = 0;
1452   GLsizei tex_height = 0;
1453   GLenum tex_type = 0;
1454   GLenum tex_format = 0;
1455   bool level_is_same =
1456       texture->GetLevelSize(args.target, args.level, &tex_width, &tex_height) &&
1457       texture->GetLevelType(args.target, args.level, &tex_type, &tex_format) &&
1458       args.width == tex_width && args.height == tex_height &&
1459       args.type == tex_type && args.format == tex_format;
1460
1461   if (level_is_same && !args.pixels) {
1462     // Just set the level texture but mark the texture as uncleared.
1463     SetLevelInfo(
1464         texture_ref,
1465         args.target, args.level, args.internal_format, args.width, args.height,
1466         1, args.border, args.format, args.type, false);
1467     texture_state->tex_image_2d_failed = false;
1468     return;
1469   }
1470
1471   if (texture->IsAttachedToFramebuffer()) {
1472     framebuffer_state->clear_state_dirty = true;
1473   }
1474
1475   if (!texture_state->teximage2d_faster_than_texsubimage2d &&
1476       level_is_same && args.pixels) {
1477     {
1478       ScopedTextureUploadTimer timer(texture_state);
1479       glTexSubImage2D(args.target, args.level, 0, 0, args.width, args.height,
1480                       args.format, args.type, args.pixels);
1481     }
1482     SetLevelCleared(texture_ref, args.target, args.level, true);
1483     texture_state->tex_image_2d_failed = false;
1484     return;
1485   }
1486
1487   ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glTexImage2D");
1488   {
1489     ScopedTextureUploadTimer timer(texture_state);
1490     glTexImage2D(
1491         args.target, args.level, args.internal_format, args.width, args.height,
1492         args.border, args.format, args.type, args.pixels);
1493   }
1494   GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glTexImage2D");
1495   if (error == GL_NO_ERROR) {
1496     SetLevelInfo(
1497         texture_ref,
1498         args.target, args.level, args.internal_format, args.width, args.height,
1499         1, args.border, args.format, args.type, args.pixels != NULL);
1500     texture_state->tex_image_2d_failed = false;
1501   }
1502 }
1503
1504 ScopedTextureUploadTimer::ScopedTextureUploadTimer(
1505     DecoderTextureState* texture_state)
1506     : texture_state_(texture_state),
1507       begin_time_(base::TimeTicks::HighResNow()) {
1508 }
1509
1510 ScopedTextureUploadTimer::~ScopedTextureUploadTimer() {
1511   texture_state_->texture_upload_count++;
1512   texture_state_->total_texture_upload_time +=
1513       base::TimeTicks::HighResNow() - begin_time_;
1514 }
1515
1516 }  // namespace gles2
1517 }  // namespace gpu