Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / gpu / command_buffer / service / texture_manager.cc
blob2596dca2129b4db8679640043ff5209214f4aecb
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.
5 #include "gpu/command_buffer/service/texture_manager.h"
7 #include <algorithm>
8 #include <set>
9 #include <utility>
11 #include "base/bits.h"
12 #include "base/lazy_instance.h"
13 #include "base/strings/stringprintf.h"
14 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
15 #include "gpu/command_buffer/service/context_state.h"
16 #include "gpu/command_buffer/service/error_state.h"
17 #include "gpu/command_buffer/service/feature_info.h"
18 #include "gpu/command_buffer/service/framebuffer_manager.h"
19 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
20 #include "gpu/command_buffer/service/mailbox_manager.h"
21 #include "gpu/command_buffer/service/memory_tracking.h"
22 #include "ui/gl/gl_implementation.h"
24 namespace gpu {
25 namespace gles2 {
27 namespace {
29 // This should contain everything to uniquely identify a Texture.
30 const char TextureTag[] = "|Texture|";
31 struct TextureSignature {
32 GLenum target_;
33 GLint level_;
34 GLenum min_filter_;
35 GLenum mag_filter_;
36 GLenum wrap_r_;
37 GLenum wrap_s_;
38 GLenum wrap_t_;
39 GLenum usage_;
40 GLenum internal_format_;
41 GLenum compare_func_;
42 GLenum compare_mode_;
43 GLsizei width_;
44 GLsizei height_;
45 GLsizei depth_;
46 GLfloat max_lod_;
47 GLfloat min_lod_;
48 GLint base_level_;
49 GLint border_;
50 GLint max_level_;
51 GLenum format_;
52 GLenum type_;
53 bool has_image_;
54 bool can_render_;
55 bool can_render_to_;
56 bool npot_;
58 // Since we will be hashing this signature structure, the padding must be
59 // zero initialized. Although the C++11 specifications specify that this is
60 // true, we will use a constructor with a memset to further enforce it instead
61 // of relying on compilers adhering to this deep dark corner specification.
62 TextureSignature(GLenum target,
63 GLint level,
64 GLenum min_filter,
65 GLenum mag_filter,
66 GLenum wrap_r,
67 GLenum wrap_s,
68 GLenum wrap_t,
69 GLenum usage,
70 GLenum internal_format,
71 GLenum compare_func,
72 GLenum compare_mode,
73 GLsizei width,
74 GLsizei height,
75 GLsizei depth,
76 GLfloat max_lod,
77 GLfloat min_lod,
78 GLint base_level,
79 GLint border,
80 GLint max_level,
81 GLenum format,
82 GLenum type,
83 bool has_image,
84 bool can_render,
85 bool can_render_to,
86 bool npot) {
87 memset(this, 0, sizeof(TextureSignature));
88 target_ = target;
89 level_ = level;
90 min_filter_ = min_filter;
91 mag_filter_ = mag_filter;
92 wrap_r_ = wrap_r;
93 wrap_s_ = wrap_s;
94 wrap_t_ = wrap_t;
95 usage_ = usage;
96 internal_format_ = internal_format;
97 compare_func_ = compare_func;
98 compare_mode_ = compare_mode;
99 width_ = width;
100 height_ = height;
101 depth_ = depth;
102 max_lod_ = max_lod;
103 min_lod_ = min_lod;
104 base_level_ = base_level;
105 border_ = border;
106 max_level_ = max_level;
107 format_ = format;
108 type_ = type;
109 has_image_ = has_image;
110 can_render_ = can_render;
111 can_render_to_ = can_render_to;
112 npot_ = npot;
116 class FormatTypeValidator {
117 public:
118 FormatTypeValidator() {
119 static const FormatType kSupportedFormatTypes[] = {
120 // ES2.
121 { GL_RGB, GL_RGB, GL_UNSIGNED_BYTE },
122 { GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 },
123 { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE },
124 { GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 },
125 { GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 },
126 { GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE },
127 { GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE },
128 { GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE },
129 // Exposed by GL_OES_texture_float and GL_OES_texture_half_float
130 { GL_RGB, GL_RGB, GL_FLOAT },
131 { GL_RGBA, GL_RGBA, GL_FLOAT },
132 { GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT },
133 { GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT },
134 { GL_ALPHA, GL_ALPHA, GL_FLOAT },
135 { GL_RGB, GL_RGB, GL_HALF_FLOAT_OES },
136 { GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES },
137 { GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES },
138 { GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES },
139 { GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES },
140 // Exposed by GL_ANGLE_depth_texture
141 { GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT },
142 { GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT },
143 { GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 },
144 // Exposed by GL_EXT_sRGB
145 { GL_SRGB, GL_SRGB, GL_UNSIGNED_BYTE },
146 { GL_SRGB_ALPHA, GL_SRGB_ALPHA, GL_UNSIGNED_BYTE },
147 // Exposed by GL_EXT_texture_format_BGRA8888
148 { GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE },
149 // Exposed by GL_EXT_texture_rg
150 { GL_RED, GL_RED, GL_UNSIGNED_BYTE },
151 { GL_RG, GL_RG, GL_UNSIGNED_BYTE },
152 { GL_RED, GL_RED, GL_FLOAT },
153 { GL_RG, GL_RG, GL_FLOAT },
154 { GL_RED, GL_RED, GL_HALF_FLOAT_OES },
155 { GL_RG, GL_RG, GL_HALF_FLOAT_OES },
157 // ES3.
158 { GL_R8, GL_RED, GL_UNSIGNED_BYTE },
159 { GL_R8_SNORM, GL_RED, GL_BYTE },
160 { GL_R16F, GL_RED, GL_HALF_FLOAT },
161 { GL_R16F, GL_RED, GL_FLOAT },
162 { GL_R32F, GL_RED, GL_FLOAT },
163 { GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE },
164 { GL_R8I, GL_RED_INTEGER, GL_BYTE },
165 { GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT },
166 { GL_R16I, GL_RED_INTEGER, GL_SHORT },
167 { GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT },
168 { GL_R32I, GL_RED_INTEGER, GL_INT },
169 { GL_RG8, GL_RG, GL_UNSIGNED_BYTE },
170 { GL_RG8_SNORM, GL_RG, GL_BYTE },
171 { GL_RG16F, GL_RG, GL_HALF_FLOAT },
172 { GL_RG16F, GL_RG, GL_FLOAT },
173 { GL_RG32F, GL_RG, GL_FLOAT },
174 { GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE },
175 { GL_RG8I, GL_RG_INTEGER, GL_BYTE },
176 { GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT },
177 { GL_RG16I, GL_RG_INTEGER, GL_SHORT },
178 { GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT },
179 { GL_RG32I, GL_RG_INTEGER, GL_INT },
180 { GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE },
181 { GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE },
182 { GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE, },
183 { GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 },
184 { GL_RGB8_SNORM, GL_RGB, GL_BYTE },
185 { GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV },
186 { GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT },
187 { GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT },
188 { GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV },
189 { GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT },
190 { GL_RGB9_E5, GL_RGB, GL_FLOAT },
191 { GL_RGB16F, GL_RGB, GL_HALF_FLOAT },
192 { GL_RGB16F, GL_RGB, GL_FLOAT },
193 { GL_RGB32F, GL_RGB, GL_FLOAT },
194 { GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE },
195 { GL_RGB8I, GL_RGB_INTEGER, GL_BYTE },
196 { GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT },
197 { GL_RGB16I, GL_RGB_INTEGER, GL_SHORT },
198 { GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT },
199 { GL_RGB32I, GL_RGB_INTEGER, GL_INT },
200 { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE },
201 { GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE },
202 { GL_RGBA8_SNORM, GL_RGBA, GL_BYTE },
203 { GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE },
204 { GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 },
205 { GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV },
206 { GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE },
207 { GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 },
208 { GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV },
209 { GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT },
210 { GL_RGBA16F, GL_RGBA, GL_FLOAT },
211 { GL_RGBA32F, GL_RGBA, GL_FLOAT },
212 { GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE },
213 { GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE },
214 { GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV },
215 { GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT },
216 { GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT },
217 { GL_RGBA32I, GL_RGBA_INTEGER, GL_INT },
218 { GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT },
219 { GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT },
220 { GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT },
221 { GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT },
222 { GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT },
223 { GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 },
224 { GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL,
225 GL_FLOAT_32_UNSIGNED_INT_24_8_REV },
228 for (size_t ii = 0; ii < arraysize(kSupportedFormatTypes); ++ii) {
229 supported_combinations_.insert(kSupportedFormatTypes[ii]);
233 // This may be accessed from multiple threads.
234 bool IsValid(GLenum internal_format, GLenum format, GLenum type) const {
235 FormatType query = { internal_format, format, type };
236 return supported_combinations_.find(query) != supported_combinations_.end();
239 private:
240 // TODO(zmo): once std::tuple is allowed, switch over to that.
241 struct FormatType {
242 GLenum internal_format;
243 GLenum format;
244 GLenum type;
247 struct FormatTypeCompare {
248 bool operator() (const FormatType& lhs, const FormatType& rhs) const {
249 return (lhs.internal_format < rhs.internal_format ||
250 ((lhs.internal_format == rhs.internal_format) &&
251 (lhs.format < rhs.format)) ||
252 ((lhs.internal_format == rhs.internal_format) &&
253 (lhs.format == rhs.format) &&
254 (lhs.type < rhs.type)));
258 // This class needs to be thread safe, so once supported_combinations_
259 // are initialized in the constructor, it should never be modified later.
260 std::set<FormatType, FormatTypeCompare> supported_combinations_;
263 base::LazyInstance<const FormatTypeValidator>::Leaky g_format_type_validator =
264 LAZY_INSTANCE_INITIALIZER;
266 } // namespace anonymous
268 TextureManager::DestructionObserver::DestructionObserver() {}
270 TextureManager::DestructionObserver::~DestructionObserver() {}
272 TextureManager::~TextureManager() {
273 for (unsigned int i = 0; i < destruction_observers_.size(); i++)
274 destruction_observers_[i]->OnTextureManagerDestroying(this);
276 DCHECK(textures_.empty());
278 // If this triggers, that means something is keeping a reference to
279 // a Texture belonging to this.
280 CHECK_EQ(texture_count_, 0u);
282 DCHECK_EQ(0, num_unrenderable_textures_);
283 DCHECK_EQ(0, num_unsafe_textures_);
284 DCHECK_EQ(0, num_uncleared_mips_);
285 DCHECK_EQ(0, num_images_);
288 void TextureManager::Destroy(bool have_context) {
289 have_context_ = have_context;
290 textures_.clear();
291 for (int ii = 0; ii < kNumDefaultTextures; ++ii) {
292 default_textures_[ii] = NULL;
295 if (have_context) {
296 glDeleteTextures(arraysize(black_texture_ids_), black_texture_ids_);
299 DCHECK_EQ(0u, memory_tracker_managed_->GetMemRepresented());
300 DCHECK_EQ(0u, memory_tracker_unmanaged_->GetMemRepresented());
303 Texture::Texture(GLuint service_id)
304 : mailbox_manager_(NULL),
305 memory_tracking_ref_(NULL),
306 service_id_(service_id),
307 cleared_(true),
308 num_uncleared_mips_(0),
309 num_npot_faces_(0),
310 target_(0),
311 min_filter_(GL_NEAREST_MIPMAP_LINEAR),
312 mag_filter_(GL_LINEAR),
313 wrap_r_(GL_REPEAT),
314 wrap_s_(GL_REPEAT),
315 wrap_t_(GL_REPEAT),
316 usage_(GL_NONE),
317 pool_(GL_TEXTURE_POOL_UNMANAGED_CHROMIUM),
318 compare_func_(GL_LEQUAL),
319 compare_mode_(GL_NONE),
320 max_lod_(1000.0f),
321 min_lod_(-1000.0f),
322 base_level_(0),
323 max_level_(1000),
324 max_level_set_(-1),
325 texture_complete_(false),
326 texture_mips_dirty_(false),
327 texture_mips_complete_(false),
328 cube_complete_(false),
329 texture_level0_dirty_(false),
330 texture_level0_complete_(false),
331 npot_(false),
332 has_been_bound_(false),
333 framebuffer_attachment_count_(0),
334 immutable_(false),
335 has_images_(false),
336 estimated_size_(0),
337 can_render_condition_(CAN_RENDER_ALWAYS),
338 texture_max_anisotropy_initialized_(false) {
341 Texture::~Texture() {
342 if (mailbox_manager_)
343 mailbox_manager_->TextureDeleted(this);
346 void Texture::AddTextureRef(TextureRef* ref) {
347 DCHECK(refs_.find(ref) == refs_.end());
348 refs_.insert(ref);
349 if (!memory_tracking_ref_) {
350 memory_tracking_ref_ = ref;
351 GetMemTracker()->TrackMemAlloc(estimated_size());
355 void Texture::RemoveTextureRef(TextureRef* ref, bool have_context) {
356 if (memory_tracking_ref_ == ref) {
357 GetMemTracker()->TrackMemFree(estimated_size());
358 memory_tracking_ref_ = NULL;
360 size_t result = refs_.erase(ref);
361 DCHECK_EQ(result, 1u);
362 if (refs_.empty()) {
363 if (have_context) {
364 GLuint id = service_id();
365 glDeleteTextures(1, &id);
367 delete this;
368 } else if (memory_tracking_ref_ == NULL) {
369 // TODO(piman): tune ownership semantics for cross-context group shared
370 // textures.
371 memory_tracking_ref_ = *refs_.begin();
372 GetMemTracker()->TrackMemAlloc(estimated_size());
376 MemoryTypeTracker* Texture::GetMemTracker() {
377 DCHECK(memory_tracking_ref_);
378 return memory_tracking_ref_->manager()->GetMemTracker(pool_);
381 Texture::LevelInfo::LevelInfo()
382 : cleared(true),
383 target(0),
384 level(-1),
385 internal_format(0),
386 width(0),
387 height(0),
388 depth(0),
389 border(0),
390 format(0),
391 type(0),
392 estimated_size(0) {
395 Texture::LevelInfo::LevelInfo(const LevelInfo& rhs)
396 : cleared(rhs.cleared),
397 target(rhs.target),
398 level(rhs.level),
399 internal_format(rhs.internal_format),
400 width(rhs.width),
401 height(rhs.height),
402 depth(rhs.depth),
403 border(rhs.border),
404 format(rhs.format),
405 type(rhs.type),
406 image(rhs.image),
407 estimated_size(rhs.estimated_size) {
410 Texture::LevelInfo::~LevelInfo() {
413 Texture::FaceInfo::FaceInfo()
414 : num_mip_levels(0) {
417 Texture::FaceInfo::~FaceInfo() {
420 Texture::CanRenderCondition Texture::GetCanRenderCondition() const {
421 if (target_ == 0)
422 return CAN_RENDER_ALWAYS;
424 if (target_ != GL_TEXTURE_EXTERNAL_OES) {
425 if (face_infos_.empty()) {
426 return CAN_RENDER_NEVER;
429 const Texture::LevelInfo& first_face = face_infos_[0].level_infos[0];
430 if (first_face.width == 0 ||
431 first_face.height == 0 ||
432 first_face.depth == 0) {
433 return CAN_RENDER_NEVER;
437 bool needs_mips = NeedsMips();
438 if (needs_mips) {
439 if (!texture_complete())
440 return CAN_RENDER_NEVER;
441 if (target_ == GL_TEXTURE_CUBE_MAP && !cube_complete())
442 return CAN_RENDER_NEVER;
445 bool is_npot_compatible = !needs_mips &&
446 wrap_s_ == GL_CLAMP_TO_EDGE &&
447 wrap_t_ == GL_CLAMP_TO_EDGE;
449 if (!is_npot_compatible) {
450 if (target_ == GL_TEXTURE_RECTANGLE_ARB)
451 return CAN_RENDER_NEVER;
452 else if (npot())
453 return CAN_RENDER_ONLY_IF_NPOT;
456 return CAN_RENDER_ALWAYS;
459 bool Texture::CanRender(const FeatureInfo* feature_info) const {
460 switch (can_render_condition_) {
461 case CAN_RENDER_ALWAYS:
462 return true;
463 case CAN_RENDER_NEVER:
464 return false;
465 case CAN_RENDER_ONLY_IF_NPOT:
466 break;
468 return feature_info->feature_flags().npot_ok;
471 void Texture::AddToSignature(
472 const FeatureInfo* feature_info,
473 GLenum target,
474 GLint level,
475 std::string* signature) const {
476 DCHECK(feature_info);
477 DCHECK(signature);
478 DCHECK_GE(level, 0);
479 size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
480 DCHECK_LT(static_cast<size_t>(face_index),
481 face_infos_.size());
482 DCHECK_LT(static_cast<size_t>(level),
483 face_infos_[face_index].level_infos.size());
485 const Texture::LevelInfo& info =
486 face_infos_[face_index].level_infos[level];
488 TextureSignature signature_data(target,
489 level,
490 min_filter_,
491 mag_filter_,
492 wrap_r_,
493 wrap_s_,
494 wrap_t_,
495 usage_,
496 info.internal_format,
497 compare_func_,
498 compare_mode_,
499 info.width,
500 info.height,
501 info.depth,
502 max_lod_,
503 min_lod_,
504 base_level_,
505 info.border,
506 max_level_,
507 info.format,
508 info.type,
509 info.image.get() != NULL,
510 CanRender(feature_info),
511 CanRenderTo(),
512 npot_);
514 signature->append(TextureTag, sizeof(TextureTag));
515 signature->append(reinterpret_cast<const char*>(&signature_data),
516 sizeof(signature_data));
519 void Texture::SetMailboxManager(MailboxManager* mailbox_manager) {
520 DCHECK(!mailbox_manager_ || mailbox_manager_ == mailbox_manager);
521 mailbox_manager_ = mailbox_manager;
524 bool Texture::MarkMipmapsGenerated(
525 const FeatureInfo* feature_info) {
526 if (!CanGenerateMipmaps(feature_info)) {
527 return false;
529 for (size_t ii = 0; ii < face_infos_.size(); ++ii) {
530 const Texture::FaceInfo& face_info = face_infos_[ii];
531 const Texture::LevelInfo& level0_info = face_info.level_infos[0];
532 GLsizei width = level0_info.width;
533 GLsizei height = level0_info.height;
534 GLsizei depth = level0_info.depth;
535 GLenum target = target_ == GL_TEXTURE_2D ? GL_TEXTURE_2D :
536 GLES2Util::IndexToGLFaceTarget(ii);
538 const GLsizei num_mips = face_info.num_mip_levels;
539 for (GLsizei level = 1; level < num_mips; ++level) {
540 width = std::max(1, width >> 1);
541 height = std::max(1, height >> 1);
542 depth = std::max(1, depth >> 1);
543 SetLevelInfo(feature_info,
544 target,
545 level,
546 level0_info.internal_format,
547 width,
548 height,
549 depth,
550 level0_info.border,
551 level0_info.format,
552 level0_info.type,
553 true);
557 return true;
560 void Texture::SetTarget(
561 const FeatureInfo* feature_info, GLenum target, GLint max_levels) {
562 DCHECK_EQ(0u, target_); // you can only set this once.
563 target_ = target;
564 size_t num_faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
565 face_infos_.resize(num_faces);
566 for (size_t ii = 0; ii < num_faces; ++ii) {
567 face_infos_[ii].level_infos.resize(max_levels);
570 if (target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ARB) {
571 min_filter_ = GL_LINEAR;
572 wrap_s_ = wrap_t_ = GL_CLAMP_TO_EDGE;
575 if (target == GL_TEXTURE_EXTERNAL_OES) {
576 immutable_ = true;
578 Update(feature_info);
579 UpdateCanRenderCondition();
582 bool Texture::CanGenerateMipmaps(
583 const FeatureInfo* feature_info) const {
584 if ((npot() && !feature_info->feature_flags().npot_ok) ||
585 face_infos_.empty() ||
586 target_ == GL_TEXTURE_EXTERNAL_OES ||
587 target_ == GL_TEXTURE_RECTANGLE_ARB) {
588 return false;
591 // Can't generate mips for depth or stencil textures.
592 const Texture::LevelInfo& first = face_infos_[0].level_infos[0];
593 uint32 channels = GLES2Util::GetChannelsForFormat(first.format);
594 if (channels & (GLES2Util::kDepth | GLES2Util::kStencil)) {
595 return false;
598 // TODO(gman): Check internal_format, format and type.
599 for (size_t ii = 0; ii < face_infos_.size(); ++ii) {
600 const LevelInfo& info = face_infos_[ii].level_infos[0];
601 if ((info.target == 0) || (info.width != first.width) ||
602 (info.height != first.height) || (info.depth != 1) ||
603 (info.format != first.format) ||
604 (info.internal_format != first.internal_format) ||
605 (info.type != first.type) ||
606 feature_info->validators()->compressed_texture_format.IsValid(
607 info.internal_format) ||
608 info.image.get()) {
609 return false;
612 return true;
615 bool Texture::TextureIsNPOT(GLsizei width,
616 GLsizei height,
617 GLsizei depth) {
618 return (GLES2Util::IsNPOT(width) ||
619 GLES2Util::IsNPOT(height) ||
620 GLES2Util::IsNPOT(depth));
623 bool Texture::TextureFaceComplete(const Texture::LevelInfo& first_face,
624 size_t face_index,
625 GLenum target,
626 GLenum internal_format,
627 GLsizei width,
628 GLsizei height,
629 GLsizei depth,
630 GLenum format,
631 GLenum type) {
632 bool complete = (target != 0 && depth == 1);
633 if (face_index != 0) {
634 complete &= (width == first_face.width &&
635 height == first_face.height &&
636 internal_format == first_face.internal_format &&
637 format == first_face.format &&
638 type == first_face.type);
640 return complete;
643 bool Texture::TextureMipComplete(const Texture::LevelInfo& level0_face,
644 GLenum target,
645 GLint level,
646 GLenum internal_format,
647 GLsizei width,
648 GLsizei height,
649 GLsizei depth,
650 GLenum format,
651 GLenum type) {
652 bool complete = (target != 0);
653 if (level != 0) {
654 const GLsizei mip_width = std::max(1, level0_face.width >> level);
655 const GLsizei mip_height = std::max(1, level0_face.height >> level);
656 const GLsizei mip_depth = std::max(1, level0_face.depth >> level);
658 complete &= (width == mip_width &&
659 height == mip_height &&
660 depth == mip_depth &&
661 internal_format == level0_face.internal_format &&
662 format == level0_face.format &&
663 type == level0_face.type);
665 return complete;
668 void Texture::SetLevelCleared(GLenum target, GLint level, bool cleared) {
669 DCHECK_GE(level, 0);
670 size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
671 DCHECK_LT(static_cast<size_t>(face_index),
672 face_infos_.size());
673 DCHECK_LT(static_cast<size_t>(level),
674 face_infos_[face_index].level_infos.size());
675 Texture::LevelInfo& info =
676 face_infos_[face_index].level_infos[level];
677 UpdateMipCleared(&info, cleared);
678 UpdateCleared();
681 void Texture::UpdateCleared() {
682 if (face_infos_.empty()) {
683 return;
686 const bool cleared = (num_uncleared_mips_ == 0);
688 // If texture is uncleared and is attached to a framebuffer,
689 // that framebuffer must be marked possibly incomplete.
690 if (!cleared && IsAttachedToFramebuffer()) {
691 IncAllFramebufferStateChangeCount();
694 UpdateSafeToRenderFrom(cleared);
697 void Texture::UpdateSafeToRenderFrom(bool cleared) {
698 if (cleared_ == cleared)
699 return;
700 cleared_ = cleared;
701 int delta = cleared ? -1 : +1;
702 for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
703 (*it)->manager()->UpdateSafeToRenderFrom(delta);
706 void Texture::UpdateMipCleared(LevelInfo* info, bool cleared) {
707 if (info->cleared == cleared)
708 return;
709 info->cleared = cleared;
710 int delta = cleared ? -1 : +1;
711 num_uncleared_mips_ += delta;
712 for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
713 (*it)->manager()->UpdateUnclearedMips(delta);
716 void Texture::UpdateCanRenderCondition() {
717 CanRenderCondition can_render_condition = GetCanRenderCondition();
718 if (can_render_condition_ == can_render_condition)
719 return;
720 for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
721 (*it)->manager()->UpdateCanRenderCondition(can_render_condition_,
722 can_render_condition);
723 can_render_condition_ = can_render_condition;
726 void Texture::UpdateHasImages() {
727 if (face_infos_.empty())
728 return;
730 bool has_images = false;
731 for (size_t ii = 0; ii < face_infos_.size(); ++ii) {
732 for (size_t jj = 0; jj < face_infos_[ii].level_infos.size(); ++jj) {
733 const Texture::LevelInfo& info = face_infos_[ii].level_infos[jj];
734 if (info.image.get() != NULL) {
735 has_images = true;
736 break;
741 if (has_images_ == has_images)
742 return;
743 has_images_ = has_images;
744 int delta = has_images ? +1 : -1;
745 for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
746 (*it)->manager()->UpdateNumImages(delta);
749 void Texture::IncAllFramebufferStateChangeCount() {
750 for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
751 (*it)->manager()->IncFramebufferStateChangeCount();
754 void Texture::SetLevelInfo(
755 const FeatureInfo* feature_info,
756 GLenum target,
757 GLint level,
758 GLenum internal_format,
759 GLsizei width,
760 GLsizei height,
761 GLsizei depth,
762 GLint border,
763 GLenum format,
764 GLenum type,
765 bool cleared) {
766 DCHECK_GE(level, 0);
767 size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
768 DCHECK_LT(static_cast<size_t>(face_index),
769 face_infos_.size());
770 DCHECK_LT(static_cast<size_t>(level),
771 face_infos_[face_index].level_infos.size());
772 DCHECK_GE(width, 0);
773 DCHECK_GE(height, 0);
774 DCHECK_GE(depth, 0);
775 Texture::LevelInfo& info =
776 face_infos_[face_index].level_infos[level];
778 // Update counters only if any attributes have changed. Counters are
779 // comparisons between the old and new values so it must be done before any
780 // assignment has been done to the LevelInfo.
781 if (info.target != target ||
782 info.internal_format != internal_format ||
783 info.width != width ||
784 info.height != height ||
785 info.depth != depth ||
786 info.format != format ||
787 info.type != type) {
788 if (level == 0) {
789 // Calculate the mip level count.
790 face_infos_[face_index].num_mip_levels =
791 TextureManager::ComputeMipMapCount(target_, width, height, depth);
793 // Update NPOT face count for the first level.
794 bool prev_npot = TextureIsNPOT(info.width, info.height, info.depth);
795 bool now_npot = TextureIsNPOT(width, height, depth);
796 if (prev_npot != now_npot)
797 num_npot_faces_ += now_npot ? 1 : -1;
799 // Signify that level 0 has been changed, so they need to be reverified.
800 texture_level0_dirty_ = true;
803 // Signify that at least one of the mips has changed.
804 texture_mips_dirty_ = true;
807 info.target = target;
808 info.level = level;
809 info.internal_format = internal_format;
810 info.width = width;
811 info.height = height;
812 info.depth = depth;
813 info.border = border;
814 info.format = format;
815 info.type = type;
816 info.image = 0;
818 estimated_size_ -= info.estimated_size;
819 GLES2Util::ComputeImageDataSizes(
820 width, height, 1, format, type, 4, &info.estimated_size, NULL, NULL);
821 estimated_size_ += info.estimated_size;
823 UpdateMipCleared(&info, cleared);
824 max_level_set_ = std::max(max_level_set_, level);
825 Update(feature_info);
826 UpdateCleared();
827 UpdateCanRenderCondition();
828 UpdateHasImages();
829 if (IsAttachedToFramebuffer()) {
830 // TODO(gman): If textures tracked which framebuffers they were attached to
831 // we could just mark those framebuffers as not complete.
832 IncAllFramebufferStateChangeCount();
836 bool Texture::ValidForTexture(
837 GLint target,
838 GLint level,
839 GLint xoffset,
840 GLint yoffset,
841 GLint zoffset,
842 GLsizei width,
843 GLsizei height,
844 GLsizei depth,
845 GLenum type) const {
846 size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
847 if (level >= 0 && face_index < face_infos_.size() &&
848 static_cast<size_t>(level) < face_infos_[face_index].level_infos.size()) {
849 const LevelInfo& info = face_infos_[face_index].level_infos[level];
850 int32 max_x;
851 int32 max_y;
852 int32 max_z;
853 return SafeAddInt32(xoffset, width, &max_x) &&
854 SafeAddInt32(yoffset, height, &max_y) &&
855 SafeAddInt32(zoffset, depth, &max_z) &&
856 xoffset >= 0 &&
857 yoffset >= 0 &&
858 zoffset >= 0 &&
859 max_x <= info.width &&
860 max_y <= info.height &&
861 max_z <= info.depth &&
862 type == info.type;
864 return false;
867 bool Texture::GetLevelSize(
868 GLint target, GLint level,
869 GLsizei* width, GLsizei* height, GLsizei* depth) const {
870 DCHECK(width);
871 DCHECK(height);
872 size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
873 if (level >= 0 && face_index < face_infos_.size() &&
874 static_cast<size_t>(level) < face_infos_[face_index].level_infos.size()) {
875 const LevelInfo& info = face_infos_[face_index].level_infos[level];
876 if (info.target != 0) {
877 *width = info.width;
878 *height = info.height;
879 if (depth)
880 *depth = info.depth;
881 return true;
884 return false;
887 bool Texture::GetLevelType(
888 GLint target, GLint level, GLenum* type, GLenum* internal_format) const {
889 DCHECK(type);
890 DCHECK(internal_format);
891 size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
892 if (level >= 0 && face_index < face_infos_.size() &&
893 static_cast<size_t>(level) < face_infos_[face_index].level_infos.size()) {
894 const LevelInfo& info = face_infos_[face_index].level_infos[level];
895 if (info.target != 0) {
896 *type = info.type;
897 *internal_format = info.internal_format;
898 return true;
901 return false;
904 GLenum Texture::SetParameteri(
905 const FeatureInfo* feature_info, GLenum pname, GLint param) {
906 DCHECK(feature_info);
908 if (target_ == GL_TEXTURE_EXTERNAL_OES ||
909 target_ == GL_TEXTURE_RECTANGLE_ARB) {
910 if (pname == GL_TEXTURE_MIN_FILTER &&
911 (param != GL_NEAREST && param != GL_LINEAR))
912 return GL_INVALID_ENUM;
913 if ((pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T) &&
914 param != GL_CLAMP_TO_EDGE)
915 return GL_INVALID_ENUM;
918 switch (pname) {
919 case GL_TEXTURE_MIN_LOD:
920 case GL_TEXTURE_MAX_LOD:
922 GLfloat fparam = static_cast<GLfloat>(param);
923 return SetParameterf(feature_info, pname, fparam);
925 case GL_TEXTURE_MIN_FILTER:
926 if (!feature_info->validators()->texture_min_filter_mode.IsValid(param)) {
927 return GL_INVALID_ENUM;
929 min_filter_ = param;
930 break;
931 case GL_TEXTURE_MAG_FILTER:
932 if (!feature_info->validators()->texture_mag_filter_mode.IsValid(param)) {
933 return GL_INVALID_ENUM;
935 mag_filter_ = param;
936 break;
937 case GL_TEXTURE_POOL_CHROMIUM:
938 if (!feature_info->validators()->texture_pool.IsValid(param)) {
939 return GL_INVALID_ENUM;
941 GetMemTracker()->TrackMemFree(estimated_size());
942 pool_ = param;
943 GetMemTracker()->TrackMemAlloc(estimated_size());
944 break;
945 case GL_TEXTURE_WRAP_R:
946 if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) {
947 return GL_INVALID_ENUM;
949 wrap_r_ = param;
950 break;
951 case GL_TEXTURE_WRAP_S:
952 if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) {
953 return GL_INVALID_ENUM;
955 wrap_s_ = param;
956 break;
957 case GL_TEXTURE_WRAP_T:
958 if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) {
959 return GL_INVALID_ENUM;
961 wrap_t_ = param;
962 break;
963 case GL_TEXTURE_COMPARE_FUNC:
964 if (!feature_info->validators()->texture_compare_func.IsValid(param)) {
965 return GL_INVALID_ENUM;
967 compare_func_ = param;
968 break;
969 case GL_TEXTURE_COMPARE_MODE:
970 if (!feature_info->validators()->texture_compare_mode.IsValid(param)) {
971 return GL_INVALID_ENUM;
973 compare_mode_ = param;
974 break;
975 case GL_TEXTURE_BASE_LEVEL:
976 if (param < 0) {
977 return GL_INVALID_VALUE;
979 base_level_ = param;
980 break;
981 case GL_TEXTURE_MAX_LEVEL:
982 if (param < 0) {
983 return GL_INVALID_VALUE;
985 max_level_ = param;
986 break;
987 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
988 if (param < 1) {
989 return GL_INVALID_VALUE;
991 break;
992 case GL_TEXTURE_USAGE_ANGLE:
993 if (!feature_info->validators()->texture_usage.IsValid(param)) {
994 return GL_INVALID_ENUM;
996 usage_ = param;
997 break;
998 default:
999 NOTREACHED();
1000 return GL_INVALID_ENUM;
1002 Update(feature_info);
1003 UpdateCleared();
1004 UpdateCanRenderCondition();
1005 return GL_NO_ERROR;
1008 GLenum Texture::SetParameterf(
1009 const FeatureInfo* feature_info, GLenum pname, GLfloat param) {
1010 switch (pname) {
1011 case GL_TEXTURE_MIN_FILTER:
1012 case GL_TEXTURE_MAG_FILTER:
1013 case GL_TEXTURE_POOL_CHROMIUM:
1014 case GL_TEXTURE_WRAP_R:
1015 case GL_TEXTURE_WRAP_S:
1016 case GL_TEXTURE_WRAP_T:
1017 case GL_TEXTURE_COMPARE_FUNC:
1018 case GL_TEXTURE_COMPARE_MODE:
1019 case GL_TEXTURE_BASE_LEVEL:
1020 case GL_TEXTURE_MAX_LEVEL:
1021 case GL_TEXTURE_USAGE_ANGLE:
1023 GLint iparam = static_cast<GLint>(param);
1024 return SetParameteri(feature_info, pname, iparam);
1026 case GL_TEXTURE_MIN_LOD:
1027 min_lod_ = param;
1028 break;
1029 case GL_TEXTURE_MAX_LOD:
1030 max_lod_ = param;
1031 break;
1032 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1033 if (param < 1.f) {
1034 return GL_INVALID_VALUE;
1036 break;
1037 default:
1038 NOTREACHED();
1039 return GL_INVALID_ENUM;
1041 return GL_NO_ERROR;
1044 void Texture::Update(const FeatureInfo* feature_info) {
1045 // Update npot status.
1046 // Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others
1047 npot_ = (target_ == GL_TEXTURE_EXTERNAL_OES) || (num_npot_faces_ > 0);
1049 if (face_infos_.empty()) {
1050 texture_complete_ = false;
1051 cube_complete_ = false;
1052 return;
1055 // Update texture_complete and cube_complete status.
1056 const Texture::FaceInfo& first_face = face_infos_[0];
1057 const Texture::LevelInfo& first_level = first_face.level_infos[0];
1058 const GLsizei levels_needed = first_face.num_mip_levels;
1060 texture_complete_ =
1061 max_level_set_ >= (levels_needed - 1) && max_level_set_ >= 0;
1062 cube_complete_ = (face_infos_.size() == 6) &&
1063 (first_level.width == first_level.height);
1065 if (first_level.width == 0 || first_level.height == 0) {
1066 texture_complete_ = false;
1067 } else if (first_level.type == GL_FLOAT &&
1068 !feature_info->feature_flags().enable_texture_float_linear &&
1069 (min_filter_ != GL_NEAREST_MIPMAP_NEAREST ||
1070 mag_filter_ != GL_NEAREST)) {
1071 texture_complete_ = false;
1072 } else if (first_level.type == GL_HALF_FLOAT_OES &&
1073 !feature_info->feature_flags().enable_texture_half_float_linear &&
1074 (min_filter_ != GL_NEAREST_MIPMAP_NEAREST ||
1075 mag_filter_ != GL_NEAREST)) {
1076 texture_complete_ = false;
1079 if (cube_complete_ && texture_level0_dirty_) {
1080 texture_level0_complete_ = true;
1081 for (size_t ii = 0; ii < face_infos_.size(); ++ii) {
1082 const Texture::LevelInfo& level0 = face_infos_[ii].level_infos[0];
1083 if (!TextureFaceComplete(first_level,
1085 level0.target,
1086 level0.internal_format,
1087 level0.width,
1088 level0.height,
1089 level0.depth,
1090 level0.format,
1091 level0.type)) {
1092 texture_level0_complete_ = false;
1093 break;
1096 texture_level0_dirty_ = false;
1098 cube_complete_ &= texture_level0_complete_;
1100 if (texture_complete_ && texture_mips_dirty_) {
1101 texture_mips_complete_ = true;
1102 for (size_t ii = 0;
1103 ii < face_infos_.size() && texture_mips_complete_;
1104 ++ii) {
1105 const Texture::FaceInfo& face_info = face_infos_[ii];
1106 const Texture::LevelInfo& level0 = face_info.level_infos[0];
1107 for (GLsizei jj = 1; jj < levels_needed; ++jj) {
1108 const Texture::LevelInfo& level_info = face_infos_[ii].level_infos[jj];
1109 if (!TextureMipComplete(level0,
1110 level_info.target,
1112 level_info.internal_format,
1113 level_info.width,
1114 level_info.height,
1115 level_info.depth,
1116 level_info.format,
1117 level_info.type)) {
1118 texture_mips_complete_ = false;
1119 break;
1123 texture_mips_dirty_ = false;
1125 texture_complete_ &= texture_mips_complete_;
1128 bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) {
1129 DCHECK(decoder);
1130 if (cleared_) {
1131 return true;
1134 for (size_t ii = 0; ii < face_infos_.size(); ++ii) {
1135 const Texture::FaceInfo& face_info = face_infos_[ii];
1136 for (GLint jj = 0; jj < face_info.num_mip_levels; ++jj) {
1137 const Texture::LevelInfo& info = face_info.level_infos[jj];
1138 if (info.target != 0) {
1139 if (!ClearLevel(decoder, info.target, jj)) {
1140 return false;
1145 UpdateSafeToRenderFrom(true);
1146 return true;
1149 bool Texture::IsLevelCleared(GLenum target, GLint level) const {
1150 size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
1151 if (face_index >= face_infos_.size() ||
1152 level >= static_cast<GLint>(face_infos_[face_index].level_infos.size())) {
1153 return true;
1156 const Texture::LevelInfo& info = face_infos_[face_index].level_infos[level];
1158 return info.cleared;
1161 void Texture::InitTextureMaxAnisotropyIfNeeded(GLenum target) {
1162 if (texture_max_anisotropy_initialized_)
1163 return;
1164 texture_max_anisotropy_initialized_ = true;
1165 GLfloat params[] = { 1.0f };
1166 glTexParameterfv(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, params);
1169 bool Texture::ClearLevel(
1170 GLES2Decoder* decoder, GLenum target, GLint level) {
1171 DCHECK(decoder);
1172 size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
1173 if (face_index >= face_infos_.size() ||
1174 level >= static_cast<GLint>(face_infos_[face_index].level_infos.size())) {
1175 return true;
1178 Texture::LevelInfo& info = face_infos_[face_index].level_infos[level];
1180 DCHECK(target == info.target);
1182 if (info.target == 0 ||
1183 info.cleared ||
1184 info.width == 0 ||
1185 info.height == 0 ||
1186 info.depth == 0) {
1187 return true;
1190 // NOTE: It seems kind of gross to call back into the decoder for this
1191 // but only the decoder knows all the state (like unpack_alignment_) that's
1192 // needed to be able to call GL correctly.
1193 bool cleared = decoder->ClearLevel(
1194 this, info.target, info.level, info.internal_format, info.format,
1195 info.type, info.width, info.height, immutable_);
1196 UpdateMipCleared(&info, cleared);
1197 return info.cleared;
1200 void Texture::SetLevelImage(
1201 const FeatureInfo* feature_info,
1202 GLenum target,
1203 GLint level,
1204 gfx::GLImage* image) {
1205 DCHECK_GE(level, 0);
1206 size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
1207 DCHECK_LT(static_cast<size_t>(face_index),
1208 face_infos_.size());
1209 DCHECK_LT(static_cast<size_t>(level),
1210 face_infos_[face_index].level_infos.size());
1211 Texture::LevelInfo& info =
1212 face_infos_[face_index].level_infos[level];
1213 DCHECK_EQ(info.target, target);
1214 DCHECK_EQ(info.level, level);
1215 info.image = image;
1216 UpdateCanRenderCondition();
1217 UpdateHasImages();
1220 gfx::GLImage* Texture::GetLevelImage(GLint target, GLint level) const {
1221 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES &&
1222 target != GL_TEXTURE_RECTANGLE_ARB) {
1223 return NULL;
1226 size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
1227 if (level >= 0 && face_index < face_infos_.size() &&
1228 static_cast<size_t>(level) < face_infos_[face_index].level_infos.size()) {
1229 const LevelInfo& info = face_infos_[face_index].level_infos[level];
1230 if (info.target != 0) {
1231 return info.image.get();
1234 return NULL;
1237 void Texture::OnWillModifyPixels() {
1238 gfx::GLImage* image = GetLevelImage(target(), 0);
1239 if (image)
1240 image->WillModifyTexImage();
1243 void Texture::OnDidModifyPixels() {
1244 gfx::GLImage* image = GetLevelImage(target(), 0);
1245 if (image)
1246 image->DidModifyTexImage();
1249 TextureRef::TextureRef(TextureManager* manager,
1250 GLuint client_id,
1251 Texture* texture)
1252 : manager_(manager),
1253 texture_(texture),
1254 client_id_(client_id),
1255 num_observers_(0) {
1256 DCHECK(manager_);
1257 DCHECK(texture_);
1258 texture_->AddTextureRef(this);
1259 manager_->StartTracking(this);
1262 scoped_refptr<TextureRef> TextureRef::Create(TextureManager* manager,
1263 GLuint client_id,
1264 GLuint service_id) {
1265 return new TextureRef(manager, client_id, new Texture(service_id));
1268 TextureRef::~TextureRef() {
1269 manager_->StopTracking(this);
1270 texture_->RemoveTextureRef(this, manager_->have_context_);
1271 manager_ = NULL;
1274 TextureManager::TextureManager(MemoryTracker* memory_tracker,
1275 FeatureInfo* feature_info,
1276 GLint max_texture_size,
1277 GLint max_cube_map_texture_size,
1278 GLint max_rectangle_texture_size,
1279 GLint max_3d_texture_size,
1280 bool use_default_textures)
1281 : memory_tracker_managed_(
1282 new MemoryTypeTracker(memory_tracker, MemoryTracker::kManaged)),
1283 memory_tracker_unmanaged_(
1284 new MemoryTypeTracker(memory_tracker, MemoryTracker::kUnmanaged)),
1285 feature_info_(feature_info),
1286 framebuffer_manager_(NULL),
1287 max_texture_size_(max_texture_size),
1288 max_cube_map_texture_size_(max_cube_map_texture_size),
1289 max_rectangle_texture_size_(max_rectangle_texture_size),
1290 max_3d_texture_size_(max_3d_texture_size),
1291 max_levels_(ComputeMipMapCount(GL_TEXTURE_2D,
1292 max_texture_size,
1293 max_texture_size,
1294 max_texture_size)),
1295 max_cube_map_levels_(ComputeMipMapCount(GL_TEXTURE_CUBE_MAP,
1296 max_cube_map_texture_size,
1297 max_cube_map_texture_size,
1298 max_cube_map_texture_size)),
1299 max_3d_levels_(ComputeMipMapCount(GL_TEXTURE_3D,
1300 // Same as GL_TEXTURE_2D_ARRAY
1301 max_3d_texture_size,
1302 max_3d_texture_size,
1303 max_3d_texture_size)),
1304 use_default_textures_(use_default_textures),
1305 num_unrenderable_textures_(0),
1306 num_unsafe_textures_(0),
1307 num_uncleared_mips_(0),
1308 num_images_(0),
1309 texture_count_(0),
1310 have_context_(true) {
1311 for (int ii = 0; ii < kNumDefaultTextures; ++ii) {
1312 black_texture_ids_[ii] = 0;
1316 bool TextureManager::Initialize() {
1317 // TODO(gman): The default textures have to be real textures, not the 0
1318 // texture because we simulate non shared resources on top of shared
1319 // resources and all contexts that share resource share the same default
1320 // texture.
1321 default_textures_[kTexture2D] = CreateDefaultAndBlackTextures(
1322 GL_TEXTURE_2D, &black_texture_ids_[kTexture2D]);
1323 default_textures_[kCubeMap] = CreateDefaultAndBlackTextures(
1324 GL_TEXTURE_CUBE_MAP, &black_texture_ids_[kCubeMap]);
1326 if (feature_info_->feature_flags().oes_egl_image_external) {
1327 default_textures_[kExternalOES] = CreateDefaultAndBlackTextures(
1328 GL_TEXTURE_EXTERNAL_OES, &black_texture_ids_[kExternalOES]);
1331 if (feature_info_->feature_flags().arb_texture_rectangle) {
1332 default_textures_[kRectangleARB] = CreateDefaultAndBlackTextures(
1333 GL_TEXTURE_RECTANGLE_ARB, &black_texture_ids_[kRectangleARB]);
1336 return true;
1339 scoped_refptr<TextureRef>
1340 TextureManager::CreateDefaultAndBlackTextures(
1341 GLenum target,
1342 GLuint* black_texture) {
1343 static uint8 black[] = {0, 0, 0, 255};
1345 // Sampling a texture not associated with any EGLImage sibling will return
1346 // black values according to the spec.
1347 bool needs_initialization = (target != GL_TEXTURE_EXTERNAL_OES);
1348 bool needs_faces = (target == GL_TEXTURE_CUBE_MAP);
1350 // Make default textures and texture for replacing non-renderable textures.
1351 GLuint ids[2];
1352 const int num_ids = use_default_textures_ ? 2 : 1;
1353 glGenTextures(num_ids, ids);
1354 for (int ii = 0; ii < num_ids; ++ii) {
1355 glBindTexture(target, ids[ii]);
1356 if (needs_initialization) {
1357 if (needs_faces) {
1358 for (int jj = 0; jj < GLES2Util::kNumFaces; ++jj) {
1359 glTexImage2D(GLES2Util::IndexToGLFaceTarget(jj), 0, GL_RGBA, 1, 1, 0,
1360 GL_RGBA, GL_UNSIGNED_BYTE, black);
1362 } else {
1363 glTexImage2D(target, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
1364 GL_UNSIGNED_BYTE, black);
1368 glBindTexture(target, 0);
1370 scoped_refptr<TextureRef> default_texture;
1371 if (use_default_textures_) {
1372 default_texture = TextureRef::Create(this, 0, ids[1]);
1373 SetTarget(default_texture.get(), target);
1374 if (needs_faces) {
1375 for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) {
1376 SetLevelInfo(default_texture.get(),
1377 GLES2Util::IndexToGLFaceTarget(ii),
1379 GL_RGBA,
1384 GL_RGBA,
1385 GL_UNSIGNED_BYTE,
1386 true);
1388 } else {
1389 if (needs_initialization) {
1390 SetLevelInfo(default_texture.get(),
1391 GL_TEXTURE_2D,
1393 GL_RGBA,
1398 GL_RGBA,
1399 GL_UNSIGNED_BYTE,
1400 true);
1401 } else {
1402 SetLevelInfo(default_texture.get(),
1403 GL_TEXTURE_EXTERNAL_OES,
1405 GL_RGBA,
1410 GL_RGBA,
1411 GL_UNSIGNED_BYTE,
1412 true);
1417 *black_texture = ids[0];
1418 return default_texture;
1421 bool TextureManager::ValidForTarget(
1422 GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth) {
1423 GLsizei max_size = MaxSizeForTarget(target) >> level;
1424 return level >= 0 &&
1425 width >= 0 &&
1426 height >= 0 &&
1427 depth >= 0 &&
1428 level < MaxLevelsForTarget(target) &&
1429 width <= max_size &&
1430 height <= max_size &&
1431 depth <= max_size &&
1432 (level == 0 || feature_info_->feature_flags().npot_ok ||
1433 (!GLES2Util::IsNPOT(width) &&
1434 !GLES2Util::IsNPOT(height) &&
1435 !GLES2Util::IsNPOT(depth))) &&
1436 (target != GL_TEXTURE_CUBE_MAP || (width == height && depth == 1)) &&
1437 (target != GL_TEXTURE_2D || (depth == 1));
1440 void TextureManager::SetTarget(TextureRef* ref, GLenum target) {
1441 DCHECK(ref);
1442 ref->texture()
1443 ->SetTarget(feature_info_.get(), target, MaxLevelsForTarget(target));
1446 void TextureManager::SetLevelCleared(TextureRef* ref,
1447 GLenum target,
1448 GLint level,
1449 bool cleared) {
1450 DCHECK(ref);
1451 ref->texture()->SetLevelCleared(target, level, cleared);
1454 bool TextureManager::ClearRenderableLevels(
1455 GLES2Decoder* decoder, TextureRef* ref) {
1456 DCHECK(ref);
1457 return ref->texture()->ClearRenderableLevels(decoder);
1460 bool TextureManager::ClearTextureLevel(
1461 GLES2Decoder* decoder, TextureRef* ref,
1462 GLenum target, GLint level) {
1463 DCHECK(ref);
1464 Texture* texture = ref->texture();
1465 if (texture->num_uncleared_mips() == 0) {
1466 return true;
1468 bool result = texture->ClearLevel(decoder, target, level);
1469 texture->UpdateCleared();
1470 return result;
1473 void TextureManager::SetLevelInfo(
1474 TextureRef* ref,
1475 GLenum target,
1476 GLint level,
1477 GLenum internal_format,
1478 GLsizei width,
1479 GLsizei height,
1480 GLsizei depth,
1481 GLint border,
1482 GLenum format,
1483 GLenum type,
1484 bool cleared) {
1485 DCHECK(ref);
1486 Texture* texture = ref->texture();
1488 texture->GetMemTracker()->TrackMemFree(texture->estimated_size());
1489 texture->SetLevelInfo(feature_info_.get(),
1490 target,
1491 level,
1492 internal_format,
1493 width,
1494 height,
1495 depth,
1496 border,
1497 format,
1498 type,
1499 cleared);
1500 texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size());
1503 Texture* TextureManager::Produce(TextureRef* ref) {
1504 DCHECK(ref);
1505 return ref->texture();
1508 TextureRef* TextureManager::Consume(
1509 GLuint client_id,
1510 Texture* texture) {
1511 DCHECK(client_id);
1512 scoped_refptr<TextureRef> ref(new TextureRef(this, client_id, texture));
1513 bool result = textures_.insert(std::make_pair(client_id, ref)).second;
1514 DCHECK(result);
1515 return ref.get();
1518 void TextureManager::SetParameteri(
1519 const char* function_name, ErrorState* error_state,
1520 TextureRef* ref, GLenum pname, GLint param) {
1521 DCHECK(error_state);
1522 DCHECK(ref);
1523 Texture* texture = ref->texture();
1524 GLenum result = texture->SetParameteri(feature_info_.get(), pname, param);
1525 if (result != GL_NO_ERROR) {
1526 if (result == GL_INVALID_ENUM) {
1527 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1528 error_state, function_name, param, "param");
1529 } else {
1530 ERRORSTATE_SET_GL_ERROR_INVALID_PARAMI(
1531 error_state, result, function_name, pname, param);
1533 } else {
1534 // Texture tracking pools exist only for the command decoder, so
1535 // do not pass them on to the native GL implementation.
1536 if (pname != GL_TEXTURE_POOL_CHROMIUM) {
1537 glTexParameteri(texture->target(), pname, param);
1542 void TextureManager::SetParameterf(
1543 const char* function_name, ErrorState* error_state,
1544 TextureRef* ref, GLenum pname, GLfloat param) {
1545 DCHECK(error_state);
1546 DCHECK(ref);
1547 Texture* texture = ref->texture();
1548 GLenum result = texture->SetParameterf(feature_info_.get(), pname, param);
1549 if (result != GL_NO_ERROR) {
1550 if (result == GL_INVALID_ENUM) {
1551 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1552 error_state, function_name, pname, "pname");
1553 } else {
1554 ERRORSTATE_SET_GL_ERROR_INVALID_PARAMF(
1555 error_state, result, function_name, pname, param);
1557 } else {
1558 // Texture tracking pools exist only for the command decoder, so
1559 // do not pass them on to the native GL implementation.
1560 if (pname != GL_TEXTURE_POOL_CHROMIUM) {
1561 glTexParameterf(texture->target(), pname, param);
1566 bool TextureManager::MarkMipmapsGenerated(TextureRef* ref) {
1567 DCHECK(ref);
1568 Texture* texture = ref->texture();
1569 texture->GetMemTracker()->TrackMemFree(texture->estimated_size());
1570 bool result = texture->MarkMipmapsGenerated(feature_info_.get());
1571 texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size());
1572 return result;
1575 TextureRef* TextureManager::CreateTexture(
1576 GLuint client_id, GLuint service_id) {
1577 DCHECK_NE(0u, service_id);
1578 scoped_refptr<TextureRef> ref(TextureRef::Create(
1579 this, client_id, service_id));
1580 std::pair<TextureMap::iterator, bool> result =
1581 textures_.insert(std::make_pair(client_id, ref));
1582 DCHECK(result.second);
1583 return ref.get();
1586 TextureRef* TextureManager::GetTexture(
1587 GLuint client_id) const {
1588 TextureMap::const_iterator it = textures_.find(client_id);
1589 return it != textures_.end() ? it->second.get() : NULL;
1592 void TextureManager::RemoveTexture(GLuint client_id) {
1593 TextureMap::iterator it = textures_.find(client_id);
1594 if (it != textures_.end()) {
1595 it->second->reset_client_id();
1596 textures_.erase(it);
1600 void TextureManager::StartTracking(TextureRef* ref) {
1601 Texture* texture = ref->texture();
1602 ++texture_count_;
1603 num_uncleared_mips_ += texture->num_uncleared_mips();
1604 if (!texture->SafeToRenderFrom())
1605 ++num_unsafe_textures_;
1606 if (!texture->CanRender(feature_info_.get()))
1607 ++num_unrenderable_textures_;
1608 if (texture->HasImages())
1609 ++num_images_;
1612 void TextureManager::StopTracking(TextureRef* ref) {
1613 if (ref->num_observers()) {
1614 for (unsigned int i = 0; i < destruction_observers_.size(); i++) {
1615 destruction_observers_[i]->OnTextureRefDestroying(ref);
1617 DCHECK_EQ(ref->num_observers(), 0);
1620 Texture* texture = ref->texture();
1622 --texture_count_;
1623 if (texture->HasImages()) {
1624 DCHECK_NE(0, num_images_);
1625 --num_images_;
1627 if (!texture->CanRender(feature_info_.get())) {
1628 DCHECK_NE(0, num_unrenderable_textures_);
1629 --num_unrenderable_textures_;
1631 if (!texture->SafeToRenderFrom()) {
1632 DCHECK_NE(0, num_unsafe_textures_);
1633 --num_unsafe_textures_;
1635 num_uncleared_mips_ -= texture->num_uncleared_mips();
1636 DCHECK_GE(num_uncleared_mips_, 0);
1639 MemoryTypeTracker* TextureManager::GetMemTracker(GLenum tracking_pool) {
1640 switch (tracking_pool) {
1641 case GL_TEXTURE_POOL_MANAGED_CHROMIUM:
1642 return memory_tracker_managed_.get();
1643 break;
1644 case GL_TEXTURE_POOL_UNMANAGED_CHROMIUM:
1645 return memory_tracker_unmanaged_.get();
1646 break;
1647 default:
1648 break;
1650 NOTREACHED();
1651 return NULL;
1654 Texture* TextureManager::GetTextureForServiceId(GLuint service_id) const {
1655 // This doesn't need to be fast. It's only used during slow queries.
1656 for (TextureMap::const_iterator it = textures_.begin();
1657 it != textures_.end(); ++it) {
1658 Texture* texture = it->second->texture();
1659 if (texture->service_id() == service_id)
1660 return texture;
1662 return NULL;
1665 GLsizei TextureManager::ComputeMipMapCount(GLenum target,
1666 GLsizei width,
1667 GLsizei height,
1668 GLsizei depth) {
1669 switch (target) {
1670 case GL_TEXTURE_EXTERNAL_OES:
1671 return 1;
1672 default:
1673 return 1 +
1674 base::bits::Log2Floor(std::max(std::max(width, height), depth));
1678 void TextureManager::SetLevelImage(
1679 TextureRef* ref,
1680 GLenum target,
1681 GLint level,
1682 gfx::GLImage* image) {
1683 DCHECK(ref);
1684 ref->texture()->SetLevelImage(feature_info_.get(), target, level, image);
1687 size_t TextureManager::GetSignatureSize() const {
1688 return sizeof(TextureTag) + sizeof(TextureSignature);
1691 void TextureManager::AddToSignature(
1692 TextureRef* ref,
1693 GLenum target,
1694 GLint level,
1695 std::string* signature) const {
1696 ref->texture()->AddToSignature(feature_info_.get(), target, level, signature);
1699 void TextureManager::UpdateSafeToRenderFrom(int delta) {
1700 num_unsafe_textures_ += delta;
1701 DCHECK_GE(num_unsafe_textures_, 0);
1704 void TextureManager::UpdateUnclearedMips(int delta) {
1705 num_uncleared_mips_ += delta;
1706 DCHECK_GE(num_uncleared_mips_, 0);
1709 void TextureManager::UpdateCanRenderCondition(
1710 Texture::CanRenderCondition old_condition,
1711 Texture::CanRenderCondition new_condition) {
1712 if (old_condition == Texture::CAN_RENDER_NEVER ||
1713 (old_condition == Texture::CAN_RENDER_ONLY_IF_NPOT &&
1714 !feature_info_->feature_flags().npot_ok)) {
1715 DCHECK_GT(num_unrenderable_textures_, 0);
1716 --num_unrenderable_textures_;
1718 if (new_condition == Texture::CAN_RENDER_NEVER ||
1719 (new_condition == Texture::CAN_RENDER_ONLY_IF_NPOT &&
1720 !feature_info_->feature_flags().npot_ok))
1721 ++num_unrenderable_textures_;
1724 void TextureManager::UpdateNumImages(int delta) {
1725 num_images_ += delta;
1726 DCHECK_GE(num_images_, 0);
1729 void TextureManager::IncFramebufferStateChangeCount() {
1730 if (framebuffer_manager_)
1731 framebuffer_manager_->IncFramebufferStateChangeCount();
1734 bool TextureManager::ValidateFormatAndTypeCombination(
1735 ErrorState* error_state, const char* function_name, GLenum format,
1736 GLenum type) {
1737 // TODO(zmo): now this is only called by GLES2DecoderImpl::DoCopyTexImage2D
1738 // and is incorrect for ES3. Fix this.
1739 if (!g_format_type_validator.Get().IsValid(format, format, type)) {
1740 ERRORSTATE_SET_GL_ERROR(
1741 error_state, GL_INVALID_OPERATION, function_name,
1742 (std::string("invalid type ") +
1743 GLES2Util::GetStringEnum(type) + " for format " +
1744 GLES2Util::GetStringEnum(format)).c_str());
1745 return false;
1747 return true;
1750 bool TextureManager::ValidateTextureParameters(
1751 ErrorState* error_state, const char* function_name,
1752 GLenum format, GLenum type, GLenum internal_format, GLint level) {
1753 const Validators* validators = feature_info_->validators();
1754 if (!validators->texture_format.IsValid(format)) {
1755 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1756 error_state, function_name, format, "format");
1757 return false;
1759 if (!validators->pixel_type.IsValid(type)) {
1760 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1761 error_state, function_name, type, "type");
1762 return false;
1764 if (!g_format_type_validator.Get().IsValid(internal_format, format, type)) {
1765 ERRORSTATE_SET_GL_ERROR(
1766 error_state, GL_INVALID_OPERATION, function_name,
1767 "invalid internalformat/format/type combination");
1768 return false;
1770 // For TexSubImage calls, internal_format isn't part of the parameters,
1771 // so its validation needs to be after the internal_format/format/type
1772 // combination validation. Otherwise, an unexpected INVALID_ENUM could be
1773 // generated instead of INVALID_OPERATION.
1774 if (!validators->texture_internal_format.IsValid(internal_format)) {
1775 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1776 error_state, function_name, internal_format, "internal_format");
1777 return false;
1779 if (!feature_info_->IsES3Enabled()) {
1780 uint32 channels = GLES2Util::GetChannelsForFormat(format);
1781 if ((channels & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && level) {
1782 ERRORSTATE_SET_GL_ERROR(
1783 error_state, GL_INVALID_OPERATION, function_name,
1784 (std::string("invalid format ") + GLES2Util::GetStringEnum(format) +
1785 " for level != 0").c_str());
1786 return false;
1789 return true;
1792 // Gets the texture id for a given target.
1793 TextureRef* TextureManager::GetTextureInfoForTarget(
1794 ContextState* state, GLenum target) {
1795 TextureUnit& unit = state->texture_units[state->active_texture_unit];
1796 TextureRef* texture = NULL;
1797 switch (target) {
1798 case GL_TEXTURE_2D:
1799 texture = unit.bound_texture_2d.get();
1800 break;
1801 case GL_TEXTURE_CUBE_MAP:
1802 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1803 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1804 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1805 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1806 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1807 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1808 texture = unit.bound_texture_cube_map.get();
1809 break;
1810 case GL_TEXTURE_EXTERNAL_OES:
1811 texture = unit.bound_texture_external_oes.get();
1812 break;
1813 case GL_TEXTURE_RECTANGLE_ARB:
1814 texture = unit.bound_texture_rectangle_arb.get();
1815 break;
1816 case GL_TEXTURE_3D:
1817 texture = unit.bound_texture_3d.get();
1818 break;
1819 case GL_TEXTURE_2D_ARRAY:
1820 texture = unit.bound_texture_2d_array.get();
1821 break;
1822 default:
1823 NOTREACHED();
1824 return NULL;
1826 return texture;
1829 TextureRef* TextureManager::GetTextureInfoForTargetUnlessDefault(
1830 ContextState* state, GLenum target) {
1831 TextureRef* texture = GetTextureInfoForTarget(state, target);
1832 if (!texture)
1833 return NULL;
1834 if (texture == GetDefaultTextureInfo(target))
1835 return NULL;
1836 return texture;
1839 bool TextureManager::ValidateTexImage(
1840 ContextState* state,
1841 const char* function_name,
1842 const DoTexImageArguments& args,
1843 TextureRef** texture_ref) {
1844 ErrorState* error_state = state->GetErrorState();
1845 const Validators* validators = feature_info_->validators();
1846 if (((args.command_type == DoTexImageArguments::kTexImage2D) &&
1847 !validators->texture_target.IsValid(args.target)) ||
1848 ((args.command_type == DoTexImageArguments::kTexImage3D) &&
1849 !validators->texture_3_d_target.IsValid(args.target))) {
1850 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1851 error_state, function_name, args.target, "target");
1852 return false;
1854 if (!ValidateTextureParameters(
1855 error_state, function_name, args.format, args.type,
1856 args.internal_format, args.level)) {
1857 return false;
1859 if (!ValidForTarget(args.target, args.level,
1860 args.width, args.height, args.depth) ||
1861 args.border != 0) {
1862 ERRORSTATE_SET_GL_ERROR(
1863 error_state, GL_INVALID_VALUE, function_name,
1864 "dimensions out of range");
1865 return false;
1867 if ((GLES2Util::GetChannelsForFormat(args.format) &
1868 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && args.pixels) {
1869 ERRORSTATE_SET_GL_ERROR(
1870 error_state, GL_INVALID_OPERATION,
1871 function_name, "can not supply data for depth or stencil textures");
1872 return false;
1875 TextureRef* local_texture_ref = GetTextureInfoForTarget(state, args.target);
1876 if (!local_texture_ref) {
1877 ERRORSTATE_SET_GL_ERROR(
1878 error_state, GL_INVALID_OPERATION, function_name,
1879 "unknown texture for target");
1880 return false;
1882 if (local_texture_ref->texture()->IsImmutable()) {
1883 ERRORSTATE_SET_GL_ERROR(
1884 error_state, GL_INVALID_OPERATION, function_name,
1885 "texture is immutable");
1886 return false;
1889 if (!memory_tracker_managed_->EnsureGPUMemoryAvailable(args.pixels_size)) {
1890 ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, function_name,
1891 "out of memory");
1892 return false;
1895 // Write the TextureReference since this is valid.
1896 *texture_ref = local_texture_ref;
1897 return true;
1900 void TextureManager::ValidateAndDoTexImage(
1901 DecoderTextureState* texture_state,
1902 ContextState* state,
1903 DecoderFramebufferState* framebuffer_state,
1904 const char* function_name,
1905 const DoTexImageArguments& args) {
1906 TextureRef* texture_ref;
1907 if (!ValidateTexImage(state, function_name, args, &texture_ref)) {
1908 return;
1911 DoTexImage(texture_state, state->GetErrorState(), framebuffer_state,
1912 function_name, texture_ref, args);
1915 GLenum TextureManager::AdjustTexFormat(GLenum format) const {
1916 // TODO(bajones): GLES 3 allows for internal format and format to differ.
1917 // This logic may need to change as a result.
1918 if (gfx::GetGLImplementation() == gfx::kGLImplementationDesktopGL) {
1919 if (format == GL_SRGB_EXT)
1920 return GL_RGB;
1921 if (format == GL_SRGB_ALPHA_EXT)
1922 return GL_RGBA;
1924 return format;
1927 void TextureManager::DoTexImage(
1928 DecoderTextureState* texture_state,
1929 ErrorState* error_state,
1930 DecoderFramebufferState* framebuffer_state,
1931 const char* function_name,
1932 TextureRef* texture_ref,
1933 const DoTexImageArguments& args) {
1934 Texture* texture = texture_ref->texture();
1935 GLsizei tex_width = 0;
1936 GLsizei tex_height = 0;
1937 GLsizei tex_depth = 0;
1938 GLenum tex_type = 0;
1939 GLenum tex_format = 0;
1940 bool level_is_same =
1941 texture->GetLevelSize(
1942 args.target, args.level, &tex_width, &tex_height, &tex_depth) &&
1943 texture->GetLevelType(args.target, args.level, &tex_type, &tex_format) &&
1944 args.width == tex_width && args.height == tex_height &&
1945 args.depth == tex_depth && args.type == tex_type &&
1946 args.format == tex_format;
1948 if (level_is_same && !args.pixels) {
1949 // Just set the level texture but mark the texture as uncleared.
1950 SetLevelInfo(
1951 texture_ref,
1952 args.target, args.level, args.internal_format, args.width, args.height,
1953 args.depth, args.border, args.format, args.type, false);
1954 texture_state->tex_image_failed = false;
1955 return;
1958 if (texture->IsAttachedToFramebuffer()) {
1959 framebuffer_state->clear_state_dirty = true;
1962 if (texture_state->texsubimage_faster_than_teximage &&
1963 level_is_same && args.pixels) {
1965 ScopedTextureUploadTimer timer(texture_state);
1966 if (args.command_type == DoTexImageArguments::kTexImage3D) {
1967 glTexSubImage3D(args.target, args.level, 0, 0, 0,
1968 args.width, args.height, args.depth,
1969 args.format, args.type, args.pixels);
1970 } else {
1971 glTexSubImage2D(args.target, args.level, 0, 0, args.width, args.height,
1972 AdjustTexFormat(args.format), args.type, args.pixels);
1975 SetLevelCleared(texture_ref, args.target, args.level, true);
1976 texture_state->tex_image_failed = false;
1977 return;
1980 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, function_name);
1982 ScopedTextureUploadTimer timer(texture_state);
1983 if (args.command_type == DoTexImageArguments::kTexImage3D) {
1984 glTexImage3D(args.target, args.level, args.internal_format, args.width,
1985 args.height, args.depth, args.border, args.format,
1986 args.type, args.pixels);
1987 } else {
1988 glTexImage2D(args.target, args.level, args.internal_format, args.width,
1989 args.height, args.border, AdjustTexFormat(args.format),
1990 args.type, args.pixels);
1993 GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, function_name);
1994 if (error == GL_NO_ERROR) {
1995 SetLevelInfo(
1996 texture_ref,
1997 args.target, args.level, args.internal_format, args.width, args.height,
1998 args.depth, args.border, args.format, args.type, args.pixels != NULL);
1999 texture_state->tex_image_failed = false;
2003 ScopedTextureUploadTimer::ScopedTextureUploadTimer(
2004 DecoderTextureState* texture_state)
2005 : texture_state_(texture_state),
2006 begin_time_(base::TimeTicks::Now()) {
2009 ScopedTextureUploadTimer::~ScopedTextureUploadTimer() {
2010 texture_state_->texture_upload_count++;
2011 texture_state_->total_texture_upload_time +=
2012 base::TimeTicks::Now() - begin_time_;
2015 } // namespace gles2
2016 } // namespace gpu