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