• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
21 namespace gpu {
22 namespace gles2 {
23 
DestructionObserver()24 TextureManager::DestructionObserver::DestructionObserver() {}
25 
~DestructionObserver()26 TextureManager::DestructionObserver::~DestructionObserver() {}
27 
~TextureManager()28 TextureManager::~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 
Destroy(bool have_context)44 void 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 
Texture(GLuint service_id)59 Texture::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 
~Texture()85 Texture::~Texture() {
86   if (mailbox_manager_)
87     mailbox_manager_->TextureDeleted(this);
88 }
89 
AddTextureRef(TextureRef * ref)90 void 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 
RemoveTextureRef(TextureRef * ref,bool have_context)99 void 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 
GetMemTracker()120 MemoryTypeTracker* Texture::GetMemTracker() {
121   DCHECK(memory_tracking_ref_);
122   return memory_tracking_ref_->manager()->GetMemTracker(pool_);
123 }
124 
LevelInfo()125 Texture::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 
LevelInfo(const LevelInfo & rhs)139 Texture::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 
~LevelInfo()154 Texture::LevelInfo::~LevelInfo() {
155 }
156 
GetCanRenderCondition() const157 Texture::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 
CanRender(const FeatureInfo * feature_info) const196 bool 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 
AddToSignature(const FeatureInfo * feature_info,GLenum target,GLint level,std::string * signature) const208 void 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 
SetMailboxManager(MailboxManager * mailbox_manager)237 void Texture::SetMailboxManager(MailboxManager* mailbox_manager) {
238   DCHECK(!mailbox_manager_ || mailbox_manager_ == mailbox_manager);
239   mailbox_manager_ = mailbox_manager;
240 }
241 
MarkMipmapsGenerated(const FeatureInfo * feature_info)242 bool 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 
SetTarget(const FeatureInfo * feature_info,GLenum target,GLint max_levels)277 void 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 
CanGenerateMipmaps(const FeatureInfo * feature_info) const299 bool 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 
SetLevelCleared(GLenum target,GLint level,bool cleared)332 void 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 
UpdateCleared()345 void 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 
UpdateSafeToRenderFrom(bool cleared)374 void 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 
UpdateMipCleared(LevelInfo * info,bool cleared)383 void 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 
UpdateCanRenderCondition()393 void 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 
UpdateHasImages()403 void 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 
IncAllFramebufferStateChangeCount()426 void Texture::IncAllFramebufferStateChangeCount() {
427   for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
428     (*it)->manager()->IncFramebufferStateChangeCount();
429 }
430 
SetLevelInfo(const FeatureInfo * feature_info,GLenum target,GLint level,GLenum internal_format,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,bool cleared)431 void 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 
ValidForTexture(GLint target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum type) const483 bool 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 
GetLevelSize(GLint target,GLint level,GLsizei * width,GLsizei * height) const508 bool 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 
GetLevelType(GLint target,GLint level,GLenum * type,GLenum * internal_format) const525 bool 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 
SetParameteri(const FeatureInfo * feature_info,GLenum pname,GLint param)542 GLenum 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 
SetParameterf(const FeatureInfo * feature_info,GLenum pname,GLfloat param)610 GLenum 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 
Update(const FeatureInfo * feature_info)635 void 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 
ClearRenderableLevels(GLES2Decoder * decoder)717 bool 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 
IsLevelCleared(GLenum target,GLint level) const741 bool 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 
InitTextureMaxAnisotropyIfNeeded(GLenum target)753 void 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 
ClearLevel(GLES2Decoder * decoder,GLenum target,GLint level)761 bool 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 
SetLevelImage(const FeatureInfo * feature_info,GLenum target,GLint level,gfx::GLImage * image)792 void 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 
GetLevelImage(GLint target,GLint level) const812 gfx::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 
OnWillModifyPixels()829 void Texture::OnWillModifyPixels() {
830   gfx::GLImage* image = GetLevelImage(target(), 0);
831   if (image)
832     image->WillModifyTexImage();
833 }
834 
OnDidModifyPixels()835 void Texture::OnDidModifyPixels() {
836   gfx::GLImage* image = GetLevelImage(target(), 0);
837   if (image)
838     image->DidModifyTexImage();
839 }
840 
TextureRef(TextureManager * manager,GLuint client_id,Texture * texture)841 TextureRef::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 
Create(TextureManager * manager,GLuint client_id,GLuint service_id)854 scoped_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 
~TextureRef()860 TextureRef::~TextureRef() {
861   manager_->StopTracking(this);
862   texture_->RemoveTextureRef(this, manager_->have_context_);
863   manager_ = NULL;
864 }
865 
TextureManager(MemoryTracker * memory_tracker,FeatureInfo * feature_info,GLint max_texture_size,GLint max_cube_map_texture_size,bool use_default_textures)866 TextureManager::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 
Initialize()899 bool 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 
922 scoped_refptr<TextureRef>
CreateDefaultAndBlackTextures(GLenum target,GLuint * black_texture)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 
ValidForTarget(GLenum target,GLint level,GLsizei width,GLsizei height,GLsizei depth)1004 bool 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 
SetTarget(TextureRef * ref,GLenum target)1023 void TextureManager::SetTarget(TextureRef* ref, GLenum target) {
1024   DCHECK(ref);
1025   ref->texture()
1026       ->SetTarget(feature_info_.get(), target, MaxLevelsForTarget(target));
1027 }
1028 
SetLevelCleared(TextureRef * ref,GLenum target,GLint level,bool cleared)1029 void 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 
ClearRenderableLevels(GLES2Decoder * decoder,TextureRef * ref)1037 bool TextureManager::ClearRenderableLevels(
1038     GLES2Decoder* decoder, TextureRef* ref) {
1039   DCHECK(ref);
1040   return ref->texture()->ClearRenderableLevels(decoder);
1041 }
1042 
ClearTextureLevel(GLES2Decoder * decoder,TextureRef * ref,GLenum target,GLint level)1043 bool 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 
SetLevelInfo(TextureRef * ref,GLenum target,GLint level,GLenum internal_format,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum format,GLenum type,bool cleared)1056 void 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 
Produce(TextureRef * ref)1086 Texture* TextureManager::Produce(TextureRef* ref) {
1087   DCHECK(ref);
1088   return ref->texture();
1089 }
1090 
Consume(GLuint client_id,Texture * texture)1091 TextureRef* 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 
SetParameteri(const char * function_name,ErrorState * error_state,TextureRef * ref,GLenum pname,GLint param)1101 void 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 
SetParameterf(const char * function_name,ErrorState * error_state,TextureRef * ref,GLenum pname,GLfloat param)1125 void 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 
MarkMipmapsGenerated(TextureRef * ref)1149 bool 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 
CreateTexture(GLuint client_id,GLuint service_id)1158 TextureRef* 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 
GetTexture(GLuint client_id) const1169 TextureRef* 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 
RemoveTexture(GLuint client_id)1175 void 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 
StartTracking(TextureRef * ref)1183 void 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 
StopTracking(TextureRef * ref)1195 void 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 
GetMemTracker(GLenum tracking_pool)1222 MemoryTypeTracker* 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 
GetTextureForServiceId(GLuint service_id) const1237 Texture* 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 
ComputeMipMapCount(GLenum target,GLsizei width,GLsizei height,GLsizei depth)1248 GLsizei 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 
SetLevelImage(TextureRef * ref,GLenum target,GLint level,gfx::GLImage * image)1261 void 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 
AddToSignature(TextureRef * ref,GLenum target,GLint level,std::string * signature) const1270 void 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 
UpdateSafeToRenderFrom(int delta)1278 void TextureManager::UpdateSafeToRenderFrom(int delta) {
1279   num_unsafe_textures_ += delta;
1280   DCHECK_GE(num_unsafe_textures_, 0);
1281 }
1282 
UpdateUnclearedMips(int delta)1283 void TextureManager::UpdateUnclearedMips(int delta) {
1284   num_uncleared_mips_ += delta;
1285   DCHECK_GE(num_uncleared_mips_, 0);
1286 }
1287 
UpdateCanRenderCondition(Texture::CanRenderCondition old_condition,Texture::CanRenderCondition new_condition)1288 void 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 
UpdateNumImages(int delta)1303 void TextureManager::UpdateNumImages(int delta) {
1304   num_images_ += delta;
1305   DCHECK_GE(num_images_, 0);
1306 }
1307 
IncFramebufferStateChangeCount()1308 void TextureManager::IncFramebufferStateChangeCount() {
1309   if (framebuffer_manager_)
1310     framebuffer_manager_->IncFramebufferStateChangeCount();
1311 }
1312 
ValidateFormatAndTypeCombination(ErrorState * error_state,const char * function_name,GLenum format,GLenum type)1313 bool 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 
ValidateTextureParameters(ErrorState * error_state,const char * function_name,GLenum format,GLenum type,GLenum internal_format,GLint level)1327 bool 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.
GetTextureInfoForTarget(ContextState * state,GLenum target)1362 TextureRef* 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 
GetTextureInfoForTargetUnlessDefault(ContextState * state,GLenum target)1392 TextureRef* 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 
ValidateTexImage2D(ContextState * state,const char * function_name,const DoTextImage2DArguments & args,TextureRef ** texture_ref)1402 bool 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 
ValidateAndDoTexImage2D(DecoderTextureState * texture_state,ContextState * state,DecoderFramebufferState * framebuffer_state,const DoTextImage2DArguments & args)1465 void 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 
DoTexImage2D(DecoderTextureState * texture_state,ErrorState * error_state,DecoderFramebufferState * framebuffer_state,TextureRef * texture_ref,const DoTextImage2DArguments & args)1479 void 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 
ScopedTextureUploadTimer(DecoderTextureState * texture_state)1539 ScopedTextureUploadTimer::ScopedTextureUploadTimer(
1540     DecoderTextureState* texture_state)
1541     : texture_state_(texture_state),
1542       begin_time_(base::TimeTicks::HighResNow()) {
1543 }
1544 
~ScopedTextureUploadTimer()1545 ScopedTextureUploadTimer::~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