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