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