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