Upstream version 7.36.149.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 (unsigned int i = 0; i < destruction_observers_.size(); i++)
70     destruction_observers_[i]->OnTextureManagerDestroying(this);
71
72   DCHECK(textures_.empty());
73
74   // If this triggers, that means something is keeping a reference to
75   // a Texture belonging to this.
76   CHECK_EQ(texture_count_, 0u);
77
78   DCHECK_EQ(0, num_unrenderable_textures_);
79   DCHECK_EQ(0, num_unsafe_textures_);
80   DCHECK_EQ(0, num_uncleared_mips_);
81   DCHECK_EQ(0, num_images_);
82 }
83
84 void TextureManager::Destroy(bool have_context) {
85   have_context_ = have_context;
86   textures_.clear();
87   for (int ii = 0; ii < kNumDefaultTextures; ++ii) {
88     default_textures_[ii] = NULL;
89   }
90
91   if (have_context) {
92     glDeleteTextures(arraysize(black_texture_ids_), black_texture_ids_);
93   }
94
95   DCHECK_EQ(0u, memory_tracker_managed_->GetMemRepresented());
96   DCHECK_EQ(0u, memory_tracker_unmanaged_->GetMemRepresented());
97 }
98
99 Texture::Texture(GLuint service_id)
100     : mailbox_manager_(NULL),
101       memory_tracking_ref_(NULL),
102       service_id_(service_id),
103       cleared_(true),
104       num_uncleared_mips_(0),
105       target_(0),
106       min_filter_(GL_NEAREST_MIPMAP_LINEAR),
107       mag_filter_(GL_LINEAR),
108       wrap_s_(GL_REPEAT),
109       wrap_t_(GL_REPEAT),
110       usage_(GL_NONE),
111       pool_(GL_TEXTURE_POOL_UNMANAGED_CHROMIUM),
112       max_level_set_(-1),
113       texture_complete_(false),
114       cube_complete_(false),
115       npot_(false),
116       has_been_bound_(false),
117       framebuffer_attachment_count_(0),
118       immutable_(false),
119       has_images_(false),
120       estimated_size_(0),
121       can_render_condition_(CAN_RENDER_ALWAYS),
122       texture_max_anisotropy_initialized_(false) {
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
403   // If texture is uncleared and is attached to a framebuffer,
404   // that framebuffer must be marked possibly incomplete.
405   if (!cleared && IsAttachedToFramebuffer()) {
406     IncAllFramebufferStateChangeCount();
407   }
408
409   UpdateSafeToRenderFrom(cleared);
410 }
411
412 void Texture::UpdateSafeToRenderFrom(bool cleared) {
413   if (cleared_ == cleared)
414     return;
415   cleared_ = cleared;
416   int delta = cleared ? -1 : +1;
417   for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
418     (*it)->manager()->UpdateSafeToRenderFrom(delta);
419 }
420
421 void Texture::UpdateMipCleared(LevelInfo* info, bool cleared) {
422   if (info->cleared == cleared)
423     return;
424   info->cleared = cleared;
425   int delta = cleared ? -1 : +1;
426   num_uncleared_mips_ += delta;
427   for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
428     (*it)->manager()->UpdateUnclearedMips(delta);
429 }
430
431 void Texture::UpdateCanRenderCondition() {
432   CanRenderCondition can_render_condition = GetCanRenderCondition();
433   if (can_render_condition_ == can_render_condition)
434     return;
435   for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
436     (*it)->manager()->UpdateCanRenderCondition(can_render_condition_,
437                                                can_render_condition);
438   can_render_condition_ = can_render_condition;
439 }
440
441 void Texture::UpdateHasImages() {
442   if (level_infos_.empty())
443     return;
444
445   bool has_images = false;
446   for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
447     for (size_t jj = 0; jj < level_infos_[ii].size(); ++jj) {
448       const Texture::LevelInfo& info = level_infos_[ii][jj];
449       if (info.image.get() != NULL) {
450         has_images = true;
451         break;
452       }
453     }
454   }
455
456   if (has_images_ == has_images)
457     return;
458   has_images_ = has_images;
459   int delta = has_images ? +1 : -1;
460   for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
461     (*it)->manager()->UpdateNumImages(delta);
462 }
463
464 void Texture::IncAllFramebufferStateChangeCount() {
465   for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
466     (*it)->manager()->IncFramebufferStateChangeCount();
467 }
468
469 void Texture::SetLevelInfo(
470     const FeatureInfo* feature_info,
471     GLenum target,
472     GLint level,
473     GLenum internal_format,
474     GLsizei width,
475     GLsizei height,
476     GLsizei depth,
477     GLint border,
478     GLenum format,
479     GLenum type,
480     bool cleared) {
481   DCHECK_GE(level, 0);
482   DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)),
483             level_infos_.size());
484   DCHECK_LT(static_cast<size_t>(level),
485             level_infos_[GLTargetToFaceIndex(target)].size());
486   DCHECK_GE(width, 0);
487   DCHECK_GE(height, 0);
488   DCHECK_GE(depth, 0);
489   Texture::LevelInfo& info =
490       level_infos_[GLTargetToFaceIndex(target)][level];
491   info.target = target;
492   info.level = level;
493   info.internal_format = internal_format;
494   info.width = width;
495   info.height = height;
496   info.depth = depth;
497   info.border = border;
498   info.format = format;
499   info.type = type;
500   info.image = 0;
501
502   estimated_size_ -= info.estimated_size;
503   GLES2Util::ComputeImageDataSizes(
504       width, height, format, type, 4, &info.estimated_size, NULL, NULL);
505   estimated_size_ += info.estimated_size;
506
507   UpdateMipCleared(&info, cleared);
508   max_level_set_ = std::max(max_level_set_, level);
509   Update(feature_info);
510   UpdateCleared();
511   UpdateCanRenderCondition();
512   UpdateHasImages();
513   if (IsAttachedToFramebuffer()) {
514     // TODO(gman): If textures tracked which framebuffers they were attached to
515     // we could just mark those framebuffers as not complete.
516     IncAllFramebufferStateChangeCount();
517   }
518 }
519
520 bool Texture::ValidForTexture(
521     GLint target,
522     GLint level,
523     GLint xoffset,
524     GLint yoffset,
525     GLsizei width,
526     GLsizei height,
527     GLenum type) const {
528   size_t face_index = GLTargetToFaceIndex(target);
529   if (level >= 0 && face_index < level_infos_.size() &&
530       static_cast<size_t>(level) < level_infos_[face_index].size()) {
531     const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level];
532     int32 right;
533     int32 top;
534     return SafeAddInt32(xoffset, width, &right) &&
535            SafeAddInt32(yoffset, height, &top) &&
536            xoffset >= 0 &&
537            yoffset >= 0 &&
538            right <= info.width &&
539            top <= info.height &&
540            type == info.type;
541   }
542   return false;
543 }
544
545 bool Texture::GetLevelSize(
546     GLint target, GLint level, GLsizei* width, GLsizei* height) const {
547   DCHECK(width);
548   DCHECK(height);
549   size_t face_index = GLTargetToFaceIndex(target);
550   if (level >= 0 && face_index < level_infos_.size() &&
551       static_cast<size_t>(level) < level_infos_[face_index].size()) {
552     const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level];
553     if (info.target != 0) {
554       *width = info.width;
555       *height = info.height;
556       return true;
557     }
558   }
559   return false;
560 }
561
562 bool Texture::GetLevelType(
563     GLint target, GLint level, GLenum* type, GLenum* internal_format) const {
564   DCHECK(type);
565   DCHECK(internal_format);
566   size_t face_index = GLTargetToFaceIndex(target);
567   if (level >= 0 && face_index < level_infos_.size() &&
568       static_cast<size_t>(level) < level_infos_[face_index].size()) {
569     const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level];
570     if (info.target != 0) {
571       *type = info.type;
572       *internal_format = info.internal_format;
573       return true;
574     }
575   }
576   return false;
577 }
578
579 GLenum Texture::SetParameteri(
580     const FeatureInfo* feature_info, GLenum pname, GLint param) {
581   DCHECK(feature_info);
582
583   if (target_ == GL_TEXTURE_EXTERNAL_OES ||
584       target_ == GL_TEXTURE_RECTANGLE_ARB) {
585     if (pname == GL_TEXTURE_MIN_FILTER &&
586         (param != GL_NEAREST && param != GL_LINEAR))
587       return GL_INVALID_ENUM;
588     if ((pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T) &&
589         param != GL_CLAMP_TO_EDGE)
590       return GL_INVALID_ENUM;
591   }
592
593   switch (pname) {
594     case GL_TEXTURE_MIN_FILTER:
595       if (!feature_info->validators()->texture_min_filter_mode.IsValid(param)) {
596         return GL_INVALID_ENUM;
597       }
598       min_filter_ = param;
599       break;
600     case GL_TEXTURE_MAG_FILTER:
601       if (!feature_info->validators()->texture_mag_filter_mode.IsValid(param)) {
602         return GL_INVALID_ENUM;
603       }
604       mag_filter_ = param;
605       break;
606     case GL_TEXTURE_POOL_CHROMIUM:
607       if (!feature_info->validators()->texture_pool.IsValid(param)) {
608         return GL_INVALID_ENUM;
609       }
610       GetMemTracker()->TrackMemFree(estimated_size());
611       pool_ = param;
612       GetMemTracker()->TrackMemAlloc(estimated_size());
613       break;
614     case GL_TEXTURE_WRAP_S:
615       if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) {
616         return GL_INVALID_ENUM;
617       }
618       wrap_s_ = param;
619       break;
620     case GL_TEXTURE_WRAP_T:
621       if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) {
622         return GL_INVALID_ENUM;
623       }
624       wrap_t_ = param;
625       break;
626     case GL_TEXTURE_MAX_ANISOTROPY_EXT:
627       if (param < 1) {
628         return GL_INVALID_VALUE;
629       }
630       break;
631     case GL_TEXTURE_USAGE_ANGLE:
632       if (!feature_info->validators()->texture_usage.IsValid(param)) {
633         return GL_INVALID_ENUM;
634       }
635       usage_ = param;
636       break;
637     default:
638       NOTREACHED();
639       return GL_INVALID_ENUM;
640   }
641   Update(feature_info);
642   UpdateCleared();
643   UpdateCanRenderCondition();
644   return GL_NO_ERROR;
645 }
646
647 GLenum Texture::SetParameterf(
648     const FeatureInfo* feature_info, GLenum pname, GLfloat param) {
649   switch (pname) {
650     case GL_TEXTURE_MIN_FILTER:
651     case GL_TEXTURE_MAG_FILTER:
652     case GL_TEXTURE_POOL_CHROMIUM:
653     case GL_TEXTURE_WRAP_S:
654     case GL_TEXTURE_WRAP_T:
655     case GL_TEXTURE_USAGE_ANGLE:
656       {
657         GLint iparam = static_cast<GLint>(param);
658         return SetParameteri(feature_info, pname, iparam);
659       }
660     case GL_TEXTURE_MAX_ANISOTROPY_EXT:
661       if (param < 1.f) {
662         return GL_INVALID_VALUE;
663       }
664       break;
665     default:
666       NOTREACHED();
667       return GL_INVALID_ENUM;
668   }
669   return GL_NO_ERROR;
670 }
671
672 void Texture::Update(const FeatureInfo* feature_info) {
673   // Update npot status.
674   // Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others
675   npot_ = target_ == GL_TEXTURE_EXTERNAL_OES;
676
677   if (level_infos_.empty()) {
678     texture_complete_ = false;
679     cube_complete_ = false;
680     return;
681   }
682
683   // checks that the first mip of any face is npot.
684   for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
685     const Texture::LevelInfo& info = level_infos_[ii][0];
686     if (GLES2Util::IsNPOT(info.width) ||
687         GLES2Util::IsNPOT(info.height) ||
688         GLES2Util::IsNPOT(info.depth)) {
689       npot_ = true;
690       break;
691     }
692   }
693
694   // Update texture_complete and cube_complete status.
695   const Texture::LevelInfo& first_face = level_infos_[0][0];
696   int levels_needed = TextureManager::ComputeMipMapCount(
697       target_, first_face.width, first_face.height, first_face.depth);
698   texture_complete_ =
699       max_level_set_ >= (levels_needed - 1) && max_level_set_ >= 0;
700   cube_complete_ = (level_infos_.size() == 6) &&
701                    (first_face.width == first_face.height);
702
703   if (first_face.width == 0 || first_face.height == 0) {
704     texture_complete_ = false;
705   }
706   if (first_face.type == GL_FLOAT &&
707       !feature_info->feature_flags().enable_texture_float_linear &&
708       (min_filter_ != GL_NEAREST_MIPMAP_NEAREST ||
709        mag_filter_ != GL_NEAREST)) {
710     texture_complete_ = false;
711   } else if (first_face.type == GL_HALF_FLOAT_OES &&
712              !feature_info->feature_flags().enable_texture_half_float_linear &&
713              (min_filter_ != GL_NEAREST_MIPMAP_NEAREST ||
714               mag_filter_ != GL_NEAREST)) {
715     texture_complete_ = false;
716   }
717   for (size_t ii = 0;
718        ii < level_infos_.size() && (cube_complete_ || texture_complete_);
719        ++ii) {
720     const Texture::LevelInfo& level0 = level_infos_[ii][0];
721     if (level0.target == 0 ||
722         level0.width != first_face.width ||
723         level0.height != first_face.height ||
724         level0.depth != 1 ||
725         level0.internal_format != first_face.internal_format ||
726         level0.format != first_face.format ||
727         level0.type != first_face.type) {
728       cube_complete_ = false;
729     }
730     // Get level0 dimensions
731     GLsizei width = level0.width;
732     GLsizei height = level0.height;
733     GLsizei depth = level0.depth;
734     for (GLint jj = 1; jj < levels_needed; ++jj) {
735       // compute required size for mip.
736       width = std::max(1, width >> 1);
737       height = std::max(1, height >> 1);
738       depth = std::max(1, depth >> 1);
739       const Texture::LevelInfo& info = level_infos_[ii][jj];
740       if (info.target == 0 ||
741           info.width != width ||
742           info.height != height ||
743           info.depth != depth ||
744           info.internal_format != level0.internal_format ||
745           info.format != level0.format ||
746           info.type != level0.type) {
747         texture_complete_ = false;
748         break;
749       }
750     }
751   }
752 }
753
754 bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) {
755   DCHECK(decoder);
756   if (cleared_) {
757     return true;
758   }
759
760   const Texture::LevelInfo& first_face = level_infos_[0][0];
761   int levels_needed = TextureManager::ComputeMipMapCount(
762       target_, first_face.width, first_face.height, first_face.depth);
763
764   for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
765     for (GLint jj = 0; jj < levels_needed; ++jj) {
766       Texture::LevelInfo& info = level_infos_[ii][jj];
767       if (info.target != 0) {
768         if (!ClearLevel(decoder, info.target, jj)) {
769           return false;
770         }
771       }
772     }
773   }
774   UpdateSafeToRenderFrom(true);
775   return true;
776 }
777
778 bool Texture::IsLevelCleared(GLenum target, GLint level) const {
779   size_t face_index = GLTargetToFaceIndex(target);
780   if (face_index >= level_infos_.size() ||
781       level >= static_cast<GLint>(level_infos_[face_index].size())) {
782     return true;
783   }
784
785   const Texture::LevelInfo& info = level_infos_[face_index][level];
786
787   return info.cleared;
788 }
789
790 void Texture::InitTextureMaxAnisotropyIfNeeded(GLenum target) {
791   if (texture_max_anisotropy_initialized_)
792     return;
793   texture_max_anisotropy_initialized_ = true;
794   GLfloat params[] = { 1.0f };
795   glTexParameterfv(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, params);
796 }
797
798 bool Texture::ClearLevel(
799     GLES2Decoder* decoder, GLenum target, GLint level) {
800   DCHECK(decoder);
801   size_t face_index = GLTargetToFaceIndex(target);
802   if (face_index >= level_infos_.size() ||
803       level >= static_cast<GLint>(level_infos_[face_index].size())) {
804     return true;
805   }
806
807   Texture::LevelInfo& info = level_infos_[face_index][level];
808
809   DCHECK(target == info.target);
810
811   if (info.target == 0 ||
812       info.cleared ||
813       info.width == 0 ||
814       info.height == 0 ||
815       info.depth == 0) {
816     return true;
817   }
818
819   // NOTE: It seems kind of gross to call back into the decoder for this
820   // but only the decoder knows all the state (like unpack_alignment_) that's
821   // needed to be able to call GL correctly.
822   bool cleared = decoder->ClearLevel(
823       service_id_, target_, info.target, info.level, info.internal_format,
824       info.format, info.type, info.width, info.height, immutable_);
825   UpdateMipCleared(&info, cleared);
826   return info.cleared;
827 }
828
829 void Texture::SetLevelImage(
830     const FeatureInfo* feature_info,
831     GLenum target,
832     GLint level,
833     gfx::GLImage* image) {
834   DCHECK_GE(level, 0);
835   DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)),
836             level_infos_.size());
837   DCHECK_LT(static_cast<size_t>(level),
838             level_infos_[GLTargetToFaceIndex(target)].size());
839   Texture::LevelInfo& info =
840       level_infos_[GLTargetToFaceIndex(target)][level];
841   DCHECK_EQ(info.target, target);
842   DCHECK_EQ(info.level, level);
843   info.image = image;
844   UpdateCanRenderCondition();
845   UpdateHasImages();
846 }
847
848 gfx::GLImage* Texture::GetLevelImage(GLint target, GLint level) const {
849   if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES &&
850       target != GL_TEXTURE_RECTANGLE_ARB) {
851     return NULL;
852   }
853
854   size_t face_index = GLTargetToFaceIndex(target);
855   if (level >= 0 && face_index < level_infos_.size() &&
856       static_cast<size_t>(level) < level_infos_[face_index].size()) {
857     const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level];
858     if (info.target != 0) {
859       return info.image.get();
860     }
861   }
862   return 0;
863 }
864
865 void Texture::OnWillModifyPixels() {
866   gfx::GLImage* image = GetLevelImage(target(), 0);
867   if (image)
868     image->WillModifyTexImage();
869 }
870
871 void Texture::OnDidModifyPixels() {
872   gfx::GLImage* image = GetLevelImage(target(), 0);
873   if (image)
874     image->DidModifyTexImage();
875 }
876
877 TextureRef::TextureRef(TextureManager* manager,
878                        GLuint client_id,
879                        Texture* texture)
880     : manager_(manager),
881       texture_(texture),
882       client_id_(client_id),
883       num_observers_(0) {
884   DCHECK(manager_);
885   DCHECK(texture_);
886   texture_->AddTextureRef(this);
887   manager_->StartTracking(this);
888 }
889
890 scoped_refptr<TextureRef> TextureRef::Create(TextureManager* manager,
891                                              GLuint client_id,
892                                              GLuint service_id) {
893   return new TextureRef(manager, client_id, new Texture(service_id));
894 }
895
896 TextureRef::~TextureRef() {
897   manager_->StopTracking(this);
898   texture_->RemoveTextureRef(this, manager_->have_context_);
899   manager_ = NULL;
900 }
901
902 TextureManager::TextureManager(MemoryTracker* memory_tracker,
903                                FeatureInfo* feature_info,
904                                GLint max_texture_size,
905                                GLint max_cube_map_texture_size,
906                                bool use_default_textures)
907     : memory_tracker_managed_(
908           new MemoryTypeTracker(memory_tracker, MemoryTracker::kManaged)),
909       memory_tracker_unmanaged_(
910           new MemoryTypeTracker(memory_tracker, MemoryTracker::kUnmanaged)),
911       feature_info_(feature_info),
912       framebuffer_manager_(NULL),
913       max_texture_size_(max_texture_size),
914       max_cube_map_texture_size_(max_cube_map_texture_size),
915       max_levels_(ComputeMipMapCount(GL_TEXTURE_2D,
916                                      max_texture_size,
917                                      max_texture_size,
918                                      max_texture_size)),
919       max_cube_map_levels_(ComputeMipMapCount(GL_TEXTURE_CUBE_MAP,
920                                               max_cube_map_texture_size,
921                                               max_cube_map_texture_size,
922                                               max_cube_map_texture_size)),
923       use_default_textures_(use_default_textures),
924       num_unrenderable_textures_(0),
925       num_unsafe_textures_(0),
926       num_uncleared_mips_(0),
927       num_images_(0),
928       texture_count_(0),
929       have_context_(true) {
930   for (int ii = 0; ii < kNumDefaultTextures; ++ii) {
931     black_texture_ids_[ii] = 0;
932   }
933 }
934
935 bool TextureManager::Initialize() {
936   // TODO(gman): The default textures have to be real textures, not the 0
937   // texture because we simulate non shared resources on top of shared
938   // resources and all contexts that share resource share the same default
939   // texture.
940   default_textures_[kTexture2D] = CreateDefaultAndBlackTextures(
941       GL_TEXTURE_2D, &black_texture_ids_[kTexture2D]);
942   default_textures_[kCubeMap] = CreateDefaultAndBlackTextures(
943       GL_TEXTURE_CUBE_MAP, &black_texture_ids_[kCubeMap]);
944
945   if (feature_info_->feature_flags().oes_egl_image_external) {
946     default_textures_[kExternalOES] = CreateDefaultAndBlackTextures(
947         GL_TEXTURE_EXTERNAL_OES, &black_texture_ids_[kExternalOES]);
948   }
949
950   if (feature_info_->feature_flags().arb_texture_rectangle) {
951     default_textures_[kRectangleARB] = CreateDefaultAndBlackTextures(
952         GL_TEXTURE_RECTANGLE_ARB, &black_texture_ids_[kRectangleARB]);
953   }
954
955   return true;
956 }
957
958 scoped_refptr<TextureRef>
959     TextureManager::CreateDefaultAndBlackTextures(
960         GLenum target,
961         GLuint* black_texture) {
962   static uint8 black[] = {0, 0, 0, 255};
963
964   // Sampling a texture not associated with any EGLImage sibling will return
965   // black values according to the spec.
966   bool needs_initialization = (target != GL_TEXTURE_EXTERNAL_OES);
967   bool needs_faces = (target == GL_TEXTURE_CUBE_MAP);
968
969   // Make default textures and texture for replacing non-renderable textures.
970   GLuint ids[2];
971   const unsigned long num_ids = use_default_textures_ ? 2 : 1;
972   glGenTextures(num_ids, ids);
973   for (unsigned long ii = 0; ii < num_ids; ++ii) {
974     glBindTexture(target, ids[ii]);
975     if (needs_initialization) {
976       if (needs_faces) {
977         for (int jj = 0; jj < GLES2Util::kNumFaces; ++jj) {
978           glTexImage2D(GLES2Util::IndexToGLFaceTarget(jj), 0, GL_RGBA, 1, 1, 0,
979                        GL_RGBA, GL_UNSIGNED_BYTE, black);
980         }
981       } else {
982         glTexImage2D(target, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
983                      GL_UNSIGNED_BYTE, black);
984       }
985     }
986   }
987   glBindTexture(target, 0);
988
989   scoped_refptr<TextureRef> default_texture;
990   if (use_default_textures_) {
991     default_texture = TextureRef::Create(this, 0, ids[1]);
992     SetTarget(default_texture.get(), target);
993     if (needs_faces) {
994       for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) {
995         SetLevelInfo(default_texture.get(),
996                      GLES2Util::IndexToGLFaceTarget(ii),
997                      0,
998                      GL_RGBA,
999                      1,
1000                      1,
1001                      1,
1002                      0,
1003                      GL_RGBA,
1004                      GL_UNSIGNED_BYTE,
1005                      true);
1006       }
1007     } else {
1008       if (needs_initialization) {
1009         SetLevelInfo(default_texture.get(),
1010                      GL_TEXTURE_2D,
1011                      0,
1012                      GL_RGBA,
1013                      1,
1014                      1,
1015                      1,
1016                      0,
1017                      GL_RGBA,
1018                      GL_UNSIGNED_BYTE,
1019                      true);
1020       } else {
1021         SetLevelInfo(default_texture.get(),
1022                      GL_TEXTURE_EXTERNAL_OES,
1023                      0,
1024                      GL_RGBA,
1025                      1,
1026                      1,
1027                      1,
1028                      0,
1029                      GL_RGBA,
1030                      GL_UNSIGNED_BYTE,
1031                      true);
1032       }
1033     }
1034   }
1035
1036   *black_texture = ids[0];
1037   return default_texture;
1038 }
1039
1040 bool TextureManager::ValidForTarget(
1041     GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth) {
1042   GLsizei max_size = MaxSizeForTarget(target) >> level;
1043   return level >= 0 &&
1044          width >= 0 &&
1045          height >= 0 &&
1046          depth >= 0 &&
1047          level < MaxLevelsForTarget(target) &&
1048          width <= max_size &&
1049          height <= max_size &&
1050          depth <= max_size &&
1051          (level == 0 || feature_info_->feature_flags().npot_ok ||
1052           (!GLES2Util::IsNPOT(width) &&
1053            !GLES2Util::IsNPOT(height) &&
1054            !GLES2Util::IsNPOT(depth))) &&
1055          (target != GL_TEXTURE_CUBE_MAP || (width == height && depth == 1)) &&
1056          (target != GL_TEXTURE_2D || (depth == 1));
1057 }
1058
1059 void TextureManager::SetTarget(TextureRef* ref, GLenum target) {
1060   DCHECK(ref);
1061   ref->texture()
1062       ->SetTarget(feature_info_.get(), target, MaxLevelsForTarget(target));
1063 }
1064
1065 void TextureManager::SetLevelCleared(TextureRef* ref,
1066                                      GLenum target,
1067                                      GLint level,
1068                                      bool cleared) {
1069   DCHECK(ref);
1070   ref->texture()->SetLevelCleared(target, level, cleared);
1071 }
1072
1073 bool TextureManager::ClearRenderableLevels(
1074     GLES2Decoder* decoder, TextureRef* ref) {
1075   DCHECK(ref);
1076   return ref->texture()->ClearRenderableLevels(decoder);
1077 }
1078
1079 bool TextureManager::ClearTextureLevel(
1080     GLES2Decoder* decoder, TextureRef* ref,
1081     GLenum target, GLint level) {
1082   DCHECK(ref);
1083   Texture* texture = ref->texture();
1084   if (texture->num_uncleared_mips() == 0) {
1085     return true;
1086   }
1087   bool result = texture->ClearLevel(decoder, target, level);
1088   texture->UpdateCleared();
1089   return result;
1090 }
1091
1092 void TextureManager::SetLevelInfo(
1093     TextureRef* ref,
1094     GLenum target,
1095     GLint level,
1096     GLenum internal_format,
1097     GLsizei width,
1098     GLsizei height,
1099     GLsizei depth,
1100     GLint border,
1101     GLenum format,
1102     GLenum type,
1103     bool cleared) {
1104   DCHECK(ref);
1105   Texture* texture = ref->texture();
1106
1107   texture->GetMemTracker()->TrackMemFree(texture->estimated_size());
1108   texture->SetLevelInfo(feature_info_.get(),
1109                         target,
1110                         level,
1111                         internal_format,
1112                         width,
1113                         height,
1114                         depth,
1115                         border,
1116                         format,
1117                         type,
1118                         cleared);
1119   texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size());
1120 }
1121
1122 Texture* TextureManager::Produce(TextureRef* ref) {
1123   DCHECK(ref);
1124   return ref->texture();
1125 }
1126
1127 TextureRef* TextureManager::Consume(
1128     GLuint client_id,
1129     Texture* texture) {
1130   DCHECK(client_id);
1131   scoped_refptr<TextureRef> ref(new TextureRef(this, client_id, texture));
1132   bool result = textures_.insert(std::make_pair(client_id, ref)).second;
1133   DCHECK(result);
1134   return ref.get();
1135 }
1136
1137 void TextureManager::SetParameteri(
1138     const char* function_name, ErrorState* error_state,
1139     TextureRef* ref, GLenum pname, GLint param) {
1140   DCHECK(error_state);
1141   DCHECK(ref);
1142   Texture* texture = ref->texture();
1143   GLenum result = texture->SetParameteri(feature_info_.get(), pname, param);
1144   if (result != GL_NO_ERROR) {
1145     if (result == GL_INVALID_ENUM) {
1146       ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1147           error_state, function_name, param, "param");
1148     } else {
1149       ERRORSTATE_SET_GL_ERROR_INVALID_PARAMI(
1150           error_state, result, function_name, pname, param);
1151     }
1152   } else {
1153     // Texture tracking pools exist only for the command decoder, so
1154     // do not pass them on to the native GL implementation.
1155     if (pname != GL_TEXTURE_POOL_CHROMIUM) {
1156       glTexParameteri(texture->target(), pname, param);
1157     }
1158   }
1159 }
1160
1161 void TextureManager::SetParameterf(
1162     const char* function_name, ErrorState* error_state,
1163     TextureRef* ref, GLenum pname, GLfloat param) {
1164   DCHECK(error_state);
1165   DCHECK(ref);
1166   Texture* texture = ref->texture();
1167   GLenum result = texture->SetParameterf(feature_info_.get(), pname, param);
1168   if (result != GL_NO_ERROR) {
1169     if (result == GL_INVALID_ENUM) {
1170       ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1171           error_state, function_name, param, "param");
1172     } else {
1173       ERRORSTATE_SET_GL_ERROR_INVALID_PARAMF(
1174           error_state, result, function_name, pname, param);
1175     }
1176   } else {
1177     // Texture tracking pools exist only for the command decoder, so
1178     // do not pass them on to the native GL implementation.
1179     if (pname != GL_TEXTURE_POOL_CHROMIUM) {
1180       glTexParameterf(texture->target(), pname, param);
1181     }
1182   }
1183 }
1184
1185 bool TextureManager::MarkMipmapsGenerated(TextureRef* ref) {
1186   DCHECK(ref);
1187   Texture* texture = ref->texture();
1188   texture->GetMemTracker()->TrackMemFree(texture->estimated_size());
1189   bool result = texture->MarkMipmapsGenerated(feature_info_.get());
1190   texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size());
1191   return result;
1192 }
1193
1194 TextureRef* TextureManager::CreateTexture(
1195     GLuint client_id, GLuint service_id) {
1196   DCHECK_NE(0u, service_id);
1197   scoped_refptr<TextureRef> ref(TextureRef::Create(
1198       this, client_id, service_id));
1199   std::pair<TextureMap::iterator, bool> result =
1200       textures_.insert(std::make_pair(client_id, ref));
1201   DCHECK(result.second);
1202   return ref.get();
1203 }
1204
1205 TextureRef* TextureManager::GetTexture(
1206     GLuint client_id) const {
1207   TextureMap::const_iterator it = textures_.find(client_id);
1208   return it != textures_.end() ? it->second.get() : NULL;
1209 }
1210
1211 void TextureManager::RemoveTexture(GLuint client_id) {
1212   TextureMap::iterator it = textures_.find(client_id);
1213   if (it != textures_.end()) {
1214     it->second->reset_client_id();
1215     textures_.erase(it);
1216   }
1217 }
1218
1219 void TextureManager::StartTracking(TextureRef* ref) {
1220   Texture* texture = ref->texture();
1221   ++texture_count_;
1222   num_uncleared_mips_ += texture->num_uncleared_mips();
1223   if (!texture->SafeToRenderFrom())
1224     ++num_unsafe_textures_;
1225   if (!texture->CanRender(feature_info_.get()))
1226     ++num_unrenderable_textures_;
1227   if (texture->HasImages())
1228     ++num_images_;
1229 }
1230
1231 void TextureManager::StopTracking(TextureRef* ref) {
1232   if (ref->num_observers()) {
1233     for (unsigned int i = 0; i < destruction_observers_.size(); i++) {
1234       destruction_observers_[i]->OnTextureRefDestroying(ref);
1235     }
1236     DCHECK_EQ(ref->num_observers(), 0);
1237   }
1238
1239   Texture* texture = ref->texture();
1240
1241   --texture_count_;
1242   if (texture->HasImages()) {
1243     DCHECK_NE(0, num_images_);
1244     --num_images_;
1245   }
1246   if (!texture->CanRender(feature_info_.get())) {
1247     DCHECK_NE(0, num_unrenderable_textures_);
1248     --num_unrenderable_textures_;
1249   }
1250   if (!texture->SafeToRenderFrom()) {
1251     DCHECK_NE(0, num_unsafe_textures_);
1252     --num_unsafe_textures_;
1253   }
1254   num_uncleared_mips_ -= texture->num_uncleared_mips();
1255   DCHECK_GE(num_uncleared_mips_, 0);
1256 }
1257
1258 MemoryTypeTracker* TextureManager::GetMemTracker(GLenum tracking_pool) {
1259   switch(tracking_pool) {
1260     case GL_TEXTURE_POOL_MANAGED_CHROMIUM:
1261       return memory_tracker_managed_.get();
1262       break;
1263     case GL_TEXTURE_POOL_UNMANAGED_CHROMIUM:
1264       return memory_tracker_unmanaged_.get();
1265       break;
1266     default:
1267       break;
1268   }
1269   NOTREACHED();
1270   return NULL;
1271 }
1272
1273 Texture* TextureManager::GetTextureForServiceId(GLuint service_id) const {
1274   // This doesn't need to be fast. It's only used during slow queries.
1275   for (TextureMap::const_iterator it = textures_.begin();
1276        it != textures_.end(); ++it) {
1277     Texture* texture = it->second->texture();
1278     if (texture->service_id() == service_id)
1279       return texture;
1280   }
1281   return NULL;
1282 }
1283
1284 GLsizei TextureManager::ComputeMipMapCount(GLenum target,
1285                                            GLsizei width,
1286                                            GLsizei height,
1287                                            GLsizei depth) {
1288   switch (target) {
1289     case GL_TEXTURE_EXTERNAL_OES:
1290       return 1;
1291     default:
1292       return 1 +
1293              base::bits::Log2Floor(std::max(std::max(width, height), depth));
1294   }
1295 }
1296
1297 void TextureManager::SetLevelImage(
1298     TextureRef* ref,
1299     GLenum target,
1300     GLint level,
1301     gfx::GLImage* image) {
1302   DCHECK(ref);
1303   ref->texture()->SetLevelImage(feature_info_.get(), target, level, image);
1304 }
1305
1306 void TextureManager::AddToSignature(
1307     TextureRef* ref,
1308     GLenum target,
1309     GLint level,
1310     std::string* signature) const {
1311   ref->texture()->AddToSignature(feature_info_.get(), target, level, signature);
1312 }
1313
1314 void TextureManager::UpdateSafeToRenderFrom(int delta) {
1315   num_unsafe_textures_ += delta;
1316   DCHECK_GE(num_unsafe_textures_, 0);
1317 }
1318
1319 void TextureManager::UpdateUnclearedMips(int delta) {
1320   num_uncleared_mips_ += delta;
1321   DCHECK_GE(num_uncleared_mips_, 0);
1322 }
1323
1324 void TextureManager::UpdateCanRenderCondition(
1325     Texture::CanRenderCondition old_condition,
1326     Texture::CanRenderCondition new_condition) {
1327   if (old_condition == Texture::CAN_RENDER_NEVER ||
1328       (old_condition == Texture::CAN_RENDER_ONLY_IF_NPOT &&
1329        !feature_info_->feature_flags().npot_ok)) {
1330     DCHECK_GT(num_unrenderable_textures_, 0);
1331     --num_unrenderable_textures_;
1332   }
1333   if (new_condition == Texture::CAN_RENDER_NEVER ||
1334       (new_condition == Texture::CAN_RENDER_ONLY_IF_NPOT &&
1335        !feature_info_->feature_flags().npot_ok))
1336     ++num_unrenderable_textures_;
1337 }
1338
1339 void TextureManager::UpdateNumImages(int delta) {
1340   num_images_ += delta;
1341   DCHECK_GE(num_images_, 0);
1342 }
1343
1344 void TextureManager::IncFramebufferStateChangeCount() {
1345   if (framebuffer_manager_)
1346     framebuffer_manager_->IncFramebufferStateChangeCount();
1347 }
1348
1349 bool TextureManager::ValidateFormatAndTypeCombination(
1350     ErrorState* error_state, const char* function_name, GLenum format,
1351     GLenum type) {
1352   if (!feature_info_->GetTextureFormatValidator(format).IsValid(type)) {
1353     ERRORSTATE_SET_GL_ERROR(
1354         error_state, GL_INVALID_OPERATION, function_name,
1355         (std::string("invalid type ") +
1356          GLES2Util::GetStringEnum(type) + " for format " +
1357          GLES2Util::GetStringEnum(format)).c_str());
1358     return false;
1359   }
1360   return true;
1361 }
1362
1363 bool TextureManager::ValidateTextureParameters(
1364     ErrorState* error_state, const char* function_name,
1365     GLenum format, GLenum type, GLenum internal_format, GLint level) {
1366   const Validators* validators = feature_info_->validators();
1367   if (!validators->texture_format.IsValid(format)) {
1368     ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1369         error_state, function_name, format, "format");
1370     return false;
1371   }
1372   if (!validators->pixel_type.IsValid(type)) {
1373     ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1374         error_state, function_name, type, "type");
1375     return false;
1376   }
1377   if (format != internal_format &&
1378       !((internal_format == GL_RGBA32F && format == GL_RGBA) ||
1379         (internal_format == GL_RGB32F && format == GL_RGB))) {
1380     ERRORSTATE_SET_GL_ERROR(
1381         error_state, GL_INVALID_OPERATION, function_name,
1382         "format != internalformat");
1383     return false;
1384   }
1385   uint32 channels = GLES2Util::GetChannelsForFormat(format);
1386   if ((channels & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && level) {
1387     ERRORSTATE_SET_GL_ERROR(
1388         error_state, GL_INVALID_OPERATION, function_name,
1389         (std::string("invalid format ") + GLES2Util::GetStringEnum(format) +
1390          " for level != 0").c_str());
1391     return false;
1392   }
1393   return ValidateFormatAndTypeCombination(error_state, function_name,
1394       format, type);
1395 }
1396
1397 // Gets the texture id for a given target.
1398 TextureRef* TextureManager::GetTextureInfoForTarget(
1399     ContextState* state, GLenum target) {
1400   TextureUnit& unit = state->texture_units[state->active_texture_unit];
1401   TextureRef* texture = NULL;
1402   switch (target) {
1403     case GL_TEXTURE_2D:
1404       texture = unit.bound_texture_2d.get();
1405       break;
1406     case GL_TEXTURE_CUBE_MAP:
1407     case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1408     case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1409     case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1410     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1411     case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1412     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1413       texture = unit.bound_texture_cube_map.get();
1414       break;
1415     case GL_TEXTURE_EXTERNAL_OES:
1416       texture = unit.bound_texture_external_oes.get();
1417       break;
1418     case GL_TEXTURE_RECTANGLE_ARB:
1419       texture = unit.bound_texture_rectangle_arb.get();
1420       break;
1421     default:
1422       NOTREACHED();
1423       return NULL;
1424   }
1425   return texture;
1426 }
1427
1428 TextureRef* TextureManager::GetTextureInfoForTargetUnlessDefault(
1429     ContextState* state, GLenum target) {
1430   TextureRef* texture = GetTextureInfoForTarget(state, target);
1431   if (!texture)
1432     return NULL;
1433   if (texture == GetDefaultTextureInfo(target))
1434     return NULL;
1435   return texture;
1436 }
1437
1438 bool TextureManager::ValidateTexImage2D(
1439     ContextState* state,
1440     const char* function_name,
1441     const DoTextImage2DArguments& args,
1442     TextureRef** texture_ref) {
1443   ErrorState* error_state = state->GetErrorState();
1444   const Validators* validators = feature_info_->validators();
1445   if (!validators->texture_target.IsValid(args.target)) {
1446     ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1447         error_state, function_name, args.target, "target");
1448     return false;
1449   }
1450   if (!validators->texture_internal_format.IsValid(args.internal_format)) {
1451     ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1452         error_state, function_name, args.internal_format,
1453         "internalformat");
1454     return false;
1455   }
1456   if (!ValidateTextureParameters(
1457       error_state, function_name, args.format, args.type,
1458       args.internal_format, args.level)) {
1459     return false;
1460   }
1461   if (!ValidForTarget(args.target, args.level, args.width, args.height, 1) ||
1462       args.border != 0) {
1463     ERRORSTATE_SET_GL_ERROR(
1464         error_state, GL_INVALID_VALUE, function_name,
1465         "dimensions out of range");
1466     return false;
1467   }
1468   if ((GLES2Util::GetChannelsForFormat(args.format) &
1469        (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && args.pixels) {
1470     ERRORSTATE_SET_GL_ERROR(
1471         error_state, GL_INVALID_OPERATION,
1472         function_name, "can not supply data for depth or stencil textures");
1473     return false;
1474   }
1475
1476   TextureRef* local_texture_ref = GetTextureInfoForTarget(state, args.target);
1477   if (!local_texture_ref) {
1478     ERRORSTATE_SET_GL_ERROR(
1479         error_state, GL_INVALID_OPERATION, function_name,
1480         "unknown texture for target");
1481     return false;
1482   }
1483   if (local_texture_ref->texture()->IsImmutable()) {
1484     ERRORSTATE_SET_GL_ERROR(
1485         error_state, GL_INVALID_OPERATION, function_name,
1486         "texture is immutable");
1487     return false;
1488   }
1489
1490   // TODO - verify that using the managed vs unmanaged does not matter.
1491   // They both use the same MemoryTracker, and this call just re-routes
1492   // to it.
1493   if (!memory_tracker_managed_->EnsureGPUMemoryAvailable(args.pixels_size)) {
1494     ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, function_name,
1495                             "out of memory");
1496     return false;
1497   }
1498
1499   // Write the TextureReference since this is valid.
1500   *texture_ref = local_texture_ref;
1501   return true;
1502 }
1503
1504 void TextureManager::ValidateAndDoTexImage2D(
1505     DecoderTextureState* texture_state,
1506     ContextState* state,
1507     DecoderFramebufferState* framebuffer_state,
1508     const DoTextImage2DArguments& args) {
1509   TextureRef* texture_ref;
1510   if (!ValidateTexImage2D(state, "glTexImage2D", args, &texture_ref)) {
1511     return;
1512   }
1513
1514   DoTexImage2D(texture_state, state->GetErrorState(), framebuffer_state,
1515                texture_ref, args);
1516 }
1517
1518 void TextureManager::DoTexImage2D(
1519     DecoderTextureState* texture_state,
1520     ErrorState* error_state,
1521     DecoderFramebufferState* framebuffer_state,
1522     TextureRef* texture_ref,
1523     const DoTextImage2DArguments& args) {
1524   Texture* texture = texture_ref->texture();
1525   GLsizei tex_width = 0;
1526   GLsizei tex_height = 0;
1527   GLenum tex_type = 0;
1528   GLenum tex_format = 0;
1529   bool level_is_same =
1530       texture->GetLevelSize(args.target, args.level, &tex_width, &tex_height) &&
1531       texture->GetLevelType(args.target, args.level, &tex_type, &tex_format) &&
1532       args.width == tex_width && args.height == tex_height &&
1533       args.type == tex_type && args.format == tex_format;
1534
1535   if (level_is_same && !args.pixels) {
1536     // Just set the level texture but mark the texture as uncleared.
1537     SetLevelInfo(
1538         texture_ref,
1539         args.target, args.level, args.internal_format, args.width, args.height,
1540         1, args.border, args.format, args.type, false);
1541     texture_state->tex_image_2d_failed = false;
1542     return;
1543   }
1544
1545   if (texture->IsAttachedToFramebuffer()) {
1546     framebuffer_state->clear_state_dirty = true;
1547   }
1548
1549   if (texture_state->texsubimage2d_faster_than_teximage2d &&
1550       level_is_same && args.pixels) {
1551     {
1552       ScopedTextureUploadTimer timer(texture_state);
1553       glTexSubImage2D(args.target, args.level, 0, 0, args.width, args.height,
1554                       args.format, args.type, args.pixels);
1555     }
1556     SetLevelCleared(texture_ref, args.target, args.level, true);
1557     texture_state->tex_image_2d_failed = false;
1558     return;
1559   }
1560
1561   ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glTexImage2D");
1562   {
1563     ScopedTextureUploadTimer timer(texture_state);
1564     glTexImage2D(
1565         args.target, args.level, args.internal_format, args.width, args.height,
1566         args.border, args.format, args.type, args.pixels);
1567   }
1568   GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glTexImage2D");
1569   if (error == GL_NO_ERROR) {
1570     SetLevelInfo(
1571         texture_ref,
1572         args.target, args.level, args.internal_format, args.width, args.height,
1573         1, args.border, args.format, args.type, args.pixels != NULL);
1574     texture_state->tex_image_2d_failed = false;
1575   }
1576 }
1577
1578 ScopedTextureUploadTimer::ScopedTextureUploadTimer(
1579     DecoderTextureState* texture_state)
1580     : texture_state_(texture_state),
1581       begin_time_(base::TimeTicks::HighResNow()) {
1582 }
1583
1584 ScopedTextureUploadTimer::~ScopedTextureUploadTimer() {
1585   texture_state_->texture_upload_count++;
1586   texture_state_->total_texture_upload_time +=
1587       base::TimeTicks::HighResNow() - begin_time_;
1588 }
1589
1590 }  // namespace gles2
1591 }  // namespace gpu