Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / gpu / command_buffer / service / texture_manager.cc
blobc7150ee98eee936d0c174cd9246505cbc691eefe
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 : target(0),
383 level(-1),
384 internal_format(0),
385 width(0),
386 height(0),
387 depth(0),
388 border(0),
389 format(0),
390 type(0),
391 estimated_size(0) {
394 Texture::LevelInfo::LevelInfo(const LevelInfo& rhs)
395 : cleared_rect(rhs.cleared_rect),
396 target(rhs.target),
397 level(rhs.level),
398 internal_format(rhs.internal_format),
399 width(rhs.width),
400 height(rhs.height),
401 depth(rhs.depth),
402 border(rhs.border),
403 format(rhs.format),
404 type(rhs.type),
405 image(rhs.image),
406 estimated_size(rhs.estimated_size) {
409 Texture::LevelInfo::~LevelInfo() {
412 Texture::FaceInfo::FaceInfo()
413 : num_mip_levels(0) {
416 Texture::FaceInfo::~FaceInfo() {
419 Texture::CanRenderCondition Texture::GetCanRenderCondition() const {
420 if (target_ == 0)
421 return CAN_RENDER_ALWAYS;
423 if (target_ != GL_TEXTURE_EXTERNAL_OES) {
424 if (face_infos_.empty()) {
425 return CAN_RENDER_NEVER;
428 const Texture::LevelInfo& first_face = face_infos_[0].level_infos[0];
429 if (first_face.width == 0 ||
430 first_face.height == 0 ||
431 first_face.depth == 0) {
432 return CAN_RENDER_NEVER;
436 bool needs_mips = NeedsMips();
437 if (needs_mips) {
438 if (!texture_complete())
439 return CAN_RENDER_NEVER;
440 if (target_ == GL_TEXTURE_CUBE_MAP && !cube_complete())
441 return CAN_RENDER_NEVER;
444 bool is_npot_compatible = !needs_mips &&
445 wrap_s_ == GL_CLAMP_TO_EDGE &&
446 wrap_t_ == GL_CLAMP_TO_EDGE;
448 if (!is_npot_compatible) {
449 if (target_ == GL_TEXTURE_RECTANGLE_ARB)
450 return CAN_RENDER_NEVER;
451 else if (npot())
452 return CAN_RENDER_ONLY_IF_NPOT;
455 return CAN_RENDER_ALWAYS;
458 bool Texture::CanRender(const FeatureInfo* feature_info) const {
459 switch (can_render_condition_) {
460 case CAN_RENDER_ALWAYS:
461 return true;
462 case CAN_RENDER_NEVER:
463 return false;
464 case CAN_RENDER_ONLY_IF_NPOT:
465 break;
467 return feature_info->feature_flags().npot_ok;
470 void Texture::AddToSignature(
471 const FeatureInfo* feature_info,
472 GLenum target,
473 GLint level,
474 std::string* signature) const {
475 DCHECK(feature_info);
476 DCHECK(signature);
477 DCHECK_GE(level, 0);
478 size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
479 DCHECK_LT(static_cast<size_t>(face_index),
480 face_infos_.size());
481 DCHECK_LT(static_cast<size_t>(level),
482 face_infos_[face_index].level_infos.size());
484 const Texture::LevelInfo& info =
485 face_infos_[face_index].level_infos[level];
487 TextureSignature signature_data(target,
488 level,
489 min_filter_,
490 mag_filter_,
491 wrap_r_,
492 wrap_s_,
493 wrap_t_,
494 usage_,
495 info.internal_format,
496 compare_func_,
497 compare_mode_,
498 info.width,
499 info.height,
500 info.depth,
501 max_lod_,
502 min_lod_,
503 base_level_,
504 info.border,
505 max_level_,
506 info.format,
507 info.type,
508 info.image.get() != NULL,
509 CanRender(feature_info),
510 CanRenderTo(),
511 npot_);
513 signature->append(TextureTag, sizeof(TextureTag));
514 signature->append(reinterpret_cast<const char*>(&signature_data),
515 sizeof(signature_data));
518 void Texture::SetMailboxManager(MailboxManager* mailbox_manager) {
519 DCHECK(!mailbox_manager_ || mailbox_manager_ == mailbox_manager);
520 mailbox_manager_ = mailbox_manager;
523 bool Texture::MarkMipmapsGenerated(
524 const FeatureInfo* feature_info) {
525 if (!CanGenerateMipmaps(feature_info)) {
526 return false;
528 for (size_t ii = 0; ii < face_infos_.size(); ++ii) {
529 const Texture::FaceInfo& face_info = face_infos_[ii];
530 const Texture::LevelInfo& level0_info = face_info.level_infos[0];
531 GLsizei width = level0_info.width;
532 GLsizei height = level0_info.height;
533 GLsizei depth = level0_info.depth;
534 GLenum target = target_ == GL_TEXTURE_2D ? GL_TEXTURE_2D :
535 GLES2Util::IndexToGLFaceTarget(ii);
537 const GLsizei num_mips = face_info.num_mip_levels;
538 for (GLsizei level = 1; level < num_mips; ++level) {
539 width = std::max(1, width >> 1);
540 height = std::max(1, height >> 1);
541 depth = std::max(1, depth >> 1);
542 SetLevelInfo(feature_info, target, level, level0_info.internal_format,
543 width, height, depth, level0_info.border, level0_info.format,
544 level0_info.type, gfx::Rect(width, height));
548 return true;
551 void Texture::SetTarget(
552 const FeatureInfo* feature_info, GLenum target, GLint max_levels) {
553 DCHECK_EQ(0u, target_); // you can only set this once.
554 target_ = target;
555 size_t num_faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
556 face_infos_.resize(num_faces);
557 for (size_t ii = 0; ii < num_faces; ++ii) {
558 face_infos_[ii].level_infos.resize(max_levels);
561 if (target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ARB) {
562 min_filter_ = GL_LINEAR;
563 wrap_s_ = wrap_t_ = GL_CLAMP_TO_EDGE;
566 if (target == GL_TEXTURE_EXTERNAL_OES) {
567 immutable_ = true;
569 Update(feature_info);
570 UpdateCanRenderCondition();
573 bool Texture::CanGenerateMipmaps(
574 const FeatureInfo* feature_info) const {
575 if ((npot() && !feature_info->feature_flags().npot_ok) ||
576 face_infos_.empty() ||
577 target_ == GL_TEXTURE_EXTERNAL_OES ||
578 target_ == GL_TEXTURE_RECTANGLE_ARB) {
579 return false;
582 // Can't generate mips for depth or stencil textures.
583 const Texture::LevelInfo& first = face_infos_[0].level_infos[0];
584 uint32 channels = GLES2Util::GetChannelsForFormat(first.format);
585 if (channels & (GLES2Util::kDepth | GLES2Util::kStencil)) {
586 return false;
589 // TODO(gman): Check internal_format, format and type.
590 for (size_t ii = 0; ii < face_infos_.size(); ++ii) {
591 const LevelInfo& info = face_infos_[ii].level_infos[0];
592 if ((info.target == 0) || (info.width != first.width) ||
593 (info.height != first.height) || (info.depth != 1) ||
594 (info.format != first.format) ||
595 (info.internal_format != first.internal_format) ||
596 (info.type != first.type) ||
597 feature_info->validators()->compressed_texture_format.IsValid(
598 info.internal_format) ||
599 info.image.get()) {
600 return false;
603 return true;
606 bool Texture::TextureIsNPOT(GLsizei width,
607 GLsizei height,
608 GLsizei depth) {
609 return (GLES2Util::IsNPOT(width) ||
610 GLES2Util::IsNPOT(height) ||
611 GLES2Util::IsNPOT(depth));
614 bool Texture::TextureFaceComplete(const Texture::LevelInfo& first_face,
615 size_t face_index,
616 GLenum target,
617 GLenum internal_format,
618 GLsizei width,
619 GLsizei height,
620 GLsizei depth,
621 GLenum format,
622 GLenum type) {
623 bool complete = (target != 0 && depth == 1);
624 if (face_index != 0) {
625 complete &= (width == first_face.width &&
626 height == first_face.height &&
627 internal_format == first_face.internal_format &&
628 format == first_face.format &&
629 type == first_face.type);
631 return complete;
634 bool Texture::TextureMipComplete(const Texture::LevelInfo& level0_face,
635 GLenum target,
636 GLint level,
637 GLenum internal_format,
638 GLsizei width,
639 GLsizei height,
640 GLsizei depth,
641 GLenum format,
642 GLenum type) {
643 bool complete = (target != 0);
644 if (level != 0) {
645 const GLsizei mip_width = std::max(1, level0_face.width >> level);
646 const GLsizei mip_height = std::max(1, level0_face.height >> level);
647 const GLsizei mip_depth = std::max(1, level0_face.depth >> level);
649 complete &= (width == mip_width &&
650 height == mip_height &&
651 depth == mip_depth &&
652 internal_format == level0_face.internal_format &&
653 format == level0_face.format &&
654 type == level0_face.type);
656 return complete;
659 void Texture::SetLevelClearedRect(GLenum target,
660 GLint level,
661 const gfx::Rect& cleared_rect) {
662 DCHECK_GE(level, 0);
663 size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
664 DCHECK_LT(static_cast<size_t>(face_index),
665 face_infos_.size());
666 DCHECK_LT(static_cast<size_t>(level),
667 face_infos_[face_index].level_infos.size());
668 Texture::LevelInfo& info =
669 face_infos_[face_index].level_infos[level];
670 UpdateMipCleared(&info, info.width, info.height, cleared_rect);
671 UpdateCleared();
674 void Texture::SetLevelCleared(GLenum target, GLint level, bool cleared) {
675 DCHECK_GE(level, 0);
676 size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
677 DCHECK_LT(static_cast<size_t>(face_index), face_infos_.size());
678 DCHECK_LT(static_cast<size_t>(level),
679 face_infos_[face_index].level_infos.size());
680 Texture::LevelInfo& info = face_infos_[face_index].level_infos[level];
681 UpdateMipCleared(&info, info.width, info.height,
682 cleared ? gfx::Rect(info.width, info.height) : gfx::Rect());
683 UpdateCleared();
686 void Texture::UpdateCleared() {
687 if (face_infos_.empty()) {
688 return;
691 const bool cleared = (num_uncleared_mips_ == 0);
693 // If texture is uncleared and is attached to a framebuffer,
694 // that framebuffer must be marked possibly incomplete.
695 if (!cleared && IsAttachedToFramebuffer()) {
696 IncAllFramebufferStateChangeCount();
699 UpdateSafeToRenderFrom(cleared);
702 void Texture::UpdateSafeToRenderFrom(bool cleared) {
703 if (cleared_ == cleared)
704 return;
705 cleared_ = cleared;
706 int delta = cleared ? -1 : +1;
707 for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
708 (*it)->manager()->UpdateSafeToRenderFrom(delta);
711 void Texture::UpdateMipCleared(LevelInfo* info,
712 GLsizei width,
713 GLsizei height,
714 const gfx::Rect& cleared_rect) {
715 bool was_cleared = info->cleared_rect == gfx::Rect(info->width, info->height);
716 info->width = width;
717 info->height = height;
718 info->cleared_rect = cleared_rect;
719 bool cleared = info->cleared_rect == gfx::Rect(info->width, info->height);
720 if (cleared == was_cleared)
721 return;
722 int delta = cleared ? -1 : +1;
723 num_uncleared_mips_ += delta;
724 for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
725 (*it)->manager()->UpdateUnclearedMips(delta);
728 void Texture::UpdateCanRenderCondition() {
729 CanRenderCondition can_render_condition = GetCanRenderCondition();
730 if (can_render_condition_ == can_render_condition)
731 return;
732 for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
733 (*it)->manager()->UpdateCanRenderCondition(can_render_condition_,
734 can_render_condition);
735 can_render_condition_ = can_render_condition;
738 void Texture::UpdateHasImages() {
739 if (face_infos_.empty())
740 return;
742 bool has_images = false;
743 for (size_t ii = 0; ii < face_infos_.size(); ++ii) {
744 for (size_t jj = 0; jj < face_infos_[ii].level_infos.size(); ++jj) {
745 const Texture::LevelInfo& info = face_infos_[ii].level_infos[jj];
746 if (info.image.get() != NULL) {
747 has_images = true;
748 break;
753 if (has_images_ == has_images)
754 return;
755 has_images_ = has_images;
756 int delta = has_images ? +1 : -1;
757 for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
758 (*it)->manager()->UpdateNumImages(delta);
761 void Texture::IncAllFramebufferStateChangeCount() {
762 for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
763 (*it)->manager()->IncFramebufferStateChangeCount();
766 void Texture::SetLevelInfo(const FeatureInfo* feature_info,
767 GLenum target,
768 GLint level,
769 GLenum internal_format,
770 GLsizei width,
771 GLsizei height,
772 GLsizei depth,
773 GLint border,
774 GLenum format,
775 GLenum type,
776 const gfx::Rect& cleared_rect) {
777 DCHECK_GE(level, 0);
778 size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
779 DCHECK_LT(static_cast<size_t>(face_index),
780 face_infos_.size());
781 DCHECK_LT(static_cast<size_t>(level),
782 face_infos_[face_index].level_infos.size());
783 DCHECK_GE(width, 0);
784 DCHECK_GE(height, 0);
785 DCHECK_GE(depth, 0);
786 Texture::LevelInfo& info =
787 face_infos_[face_index].level_infos[level];
789 // Update counters only if any attributes have changed. Counters are
790 // comparisons between the old and new values so it must be done before any
791 // assignment has been done to the LevelInfo.
792 if (info.target != target ||
793 info.internal_format != internal_format ||
794 info.width != width ||
795 info.height != height ||
796 info.depth != depth ||
797 info.format != format ||
798 info.type != type) {
799 if (level == 0) {
800 // Calculate the mip level count.
801 face_infos_[face_index].num_mip_levels =
802 TextureManager::ComputeMipMapCount(target_, width, height, depth);
804 // Update NPOT face count for the first level.
805 bool prev_npot = TextureIsNPOT(info.width, info.height, info.depth);
806 bool now_npot = TextureIsNPOT(width, height, depth);
807 if (prev_npot != now_npot)
808 num_npot_faces_ += now_npot ? 1 : -1;
810 // Signify that level 0 has been changed, so they need to be reverified.
811 texture_level0_dirty_ = true;
814 // Signify that at least one of the mips has changed.
815 texture_mips_dirty_ = true;
818 info.target = target;
819 info.level = level;
820 info.internal_format = internal_format;
821 info.depth = depth;
822 info.border = border;
823 info.format = format;
824 info.type = type;
825 info.image = 0;
827 UpdateMipCleared(&info, width, height, cleared_rect);
829 estimated_size_ -= info.estimated_size;
830 GLES2Util::ComputeImageDataSizes(
831 width, height, 1, format, type, 4, &info.estimated_size, NULL, NULL);
832 estimated_size_ += info.estimated_size;
834 max_level_set_ = std::max(max_level_set_, level);
835 Update(feature_info);
836 UpdateCleared();
837 UpdateCanRenderCondition();
838 UpdateHasImages();
839 if (IsAttachedToFramebuffer()) {
840 // TODO(gman): If textures tracked which framebuffers they were attached to
841 // we could just mark those framebuffers as not complete.
842 IncAllFramebufferStateChangeCount();
846 bool Texture::ValidForTexture(
847 GLint target,
848 GLint level,
849 GLint xoffset,
850 GLint yoffset,
851 GLint zoffset,
852 GLsizei width,
853 GLsizei height,
854 GLsizei depth,
855 GLenum type) const {
856 size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
857 if (level >= 0 && face_index < face_infos_.size() &&
858 static_cast<size_t>(level) < face_infos_[face_index].level_infos.size()) {
859 const LevelInfo& info = face_infos_[face_index].level_infos[level];
860 int32 max_x;
861 int32 max_y;
862 int32 max_z;
863 return SafeAddInt32(xoffset, width, &max_x) &&
864 SafeAddInt32(yoffset, height, &max_y) &&
865 SafeAddInt32(zoffset, depth, &max_z) &&
866 xoffset >= 0 &&
867 yoffset >= 0 &&
868 zoffset >= 0 &&
869 max_x <= info.width &&
870 max_y <= info.height &&
871 max_z <= info.depth &&
872 type == info.type;
874 return false;
877 bool Texture::GetLevelSize(
878 GLint target, GLint level,
879 GLsizei* width, GLsizei* height, GLsizei* depth) const {
880 DCHECK(width);
881 DCHECK(height);
882 size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
883 if (level >= 0 && face_index < face_infos_.size() &&
884 static_cast<size_t>(level) < face_infos_[face_index].level_infos.size()) {
885 const LevelInfo& info = face_infos_[face_index].level_infos[level];
886 if (info.target != 0) {
887 *width = info.width;
888 *height = info.height;
889 if (depth)
890 *depth = info.depth;
891 return true;
894 return false;
897 bool Texture::GetLevelType(
898 GLint target, GLint level, GLenum* type, GLenum* internal_format) const {
899 DCHECK(type);
900 DCHECK(internal_format);
901 size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
902 if (level >= 0 && face_index < face_infos_.size() &&
903 static_cast<size_t>(level) < face_infos_[face_index].level_infos.size()) {
904 const LevelInfo& info = face_infos_[face_index].level_infos[level];
905 if (info.target != 0) {
906 *type = info.type;
907 *internal_format = info.internal_format;
908 return true;
911 return false;
914 GLenum Texture::SetParameteri(
915 const FeatureInfo* feature_info, GLenum pname, GLint param) {
916 DCHECK(feature_info);
918 if (target_ == GL_TEXTURE_EXTERNAL_OES ||
919 target_ == GL_TEXTURE_RECTANGLE_ARB) {
920 if (pname == GL_TEXTURE_MIN_FILTER &&
921 (param != GL_NEAREST && param != GL_LINEAR))
922 return GL_INVALID_ENUM;
923 if ((pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T) &&
924 param != GL_CLAMP_TO_EDGE)
925 return GL_INVALID_ENUM;
928 switch (pname) {
929 case GL_TEXTURE_MIN_LOD:
930 case GL_TEXTURE_MAX_LOD:
932 GLfloat fparam = static_cast<GLfloat>(param);
933 return SetParameterf(feature_info, pname, fparam);
935 case GL_TEXTURE_MIN_FILTER:
936 if (!feature_info->validators()->texture_min_filter_mode.IsValid(param)) {
937 return GL_INVALID_ENUM;
939 min_filter_ = param;
940 break;
941 case GL_TEXTURE_MAG_FILTER:
942 if (!feature_info->validators()->texture_mag_filter_mode.IsValid(param)) {
943 return GL_INVALID_ENUM;
945 mag_filter_ = param;
946 break;
947 case GL_TEXTURE_POOL_CHROMIUM:
948 if (!feature_info->validators()->texture_pool.IsValid(param)) {
949 return GL_INVALID_ENUM;
951 GetMemTracker()->TrackMemFree(estimated_size());
952 pool_ = param;
953 GetMemTracker()->TrackMemAlloc(estimated_size());
954 break;
955 case GL_TEXTURE_WRAP_R:
956 if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) {
957 return GL_INVALID_ENUM;
959 wrap_r_ = param;
960 break;
961 case GL_TEXTURE_WRAP_S:
962 if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) {
963 return GL_INVALID_ENUM;
965 wrap_s_ = param;
966 break;
967 case GL_TEXTURE_WRAP_T:
968 if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) {
969 return GL_INVALID_ENUM;
971 wrap_t_ = param;
972 break;
973 case GL_TEXTURE_COMPARE_FUNC:
974 if (!feature_info->validators()->texture_compare_func.IsValid(param)) {
975 return GL_INVALID_ENUM;
977 compare_func_ = param;
978 break;
979 case GL_TEXTURE_COMPARE_MODE:
980 if (!feature_info->validators()->texture_compare_mode.IsValid(param)) {
981 return GL_INVALID_ENUM;
983 compare_mode_ = param;
984 break;
985 case GL_TEXTURE_BASE_LEVEL:
986 if (param < 0) {
987 return GL_INVALID_VALUE;
989 base_level_ = param;
990 break;
991 case GL_TEXTURE_MAX_LEVEL:
992 if (param < 0) {
993 return GL_INVALID_VALUE;
995 max_level_ = param;
996 break;
997 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
998 if (param < 1) {
999 return GL_INVALID_VALUE;
1001 break;
1002 case GL_TEXTURE_USAGE_ANGLE:
1003 if (!feature_info->validators()->texture_usage.IsValid(param)) {
1004 return GL_INVALID_ENUM;
1006 usage_ = param;
1007 break;
1008 default:
1009 NOTREACHED();
1010 return GL_INVALID_ENUM;
1012 Update(feature_info);
1013 UpdateCleared();
1014 UpdateCanRenderCondition();
1015 return GL_NO_ERROR;
1018 GLenum Texture::SetParameterf(
1019 const FeatureInfo* feature_info, GLenum pname, GLfloat param) {
1020 switch (pname) {
1021 case GL_TEXTURE_MIN_FILTER:
1022 case GL_TEXTURE_MAG_FILTER:
1023 case GL_TEXTURE_POOL_CHROMIUM:
1024 case GL_TEXTURE_WRAP_R:
1025 case GL_TEXTURE_WRAP_S:
1026 case GL_TEXTURE_WRAP_T:
1027 case GL_TEXTURE_COMPARE_FUNC:
1028 case GL_TEXTURE_COMPARE_MODE:
1029 case GL_TEXTURE_BASE_LEVEL:
1030 case GL_TEXTURE_MAX_LEVEL:
1031 case GL_TEXTURE_USAGE_ANGLE:
1033 GLint iparam = static_cast<GLint>(param);
1034 return SetParameteri(feature_info, pname, iparam);
1036 case GL_TEXTURE_MIN_LOD:
1037 min_lod_ = param;
1038 break;
1039 case GL_TEXTURE_MAX_LOD:
1040 max_lod_ = param;
1041 break;
1042 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
1043 if (param < 1.f) {
1044 return GL_INVALID_VALUE;
1046 break;
1047 default:
1048 NOTREACHED();
1049 return GL_INVALID_ENUM;
1051 return GL_NO_ERROR;
1054 void Texture::Update(const FeatureInfo* feature_info) {
1055 // Update npot status.
1056 // Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others
1057 npot_ = (target_ == GL_TEXTURE_EXTERNAL_OES) || (num_npot_faces_ > 0);
1059 if (face_infos_.empty()) {
1060 texture_complete_ = false;
1061 cube_complete_ = false;
1062 return;
1065 // Update texture_complete and cube_complete status.
1066 const Texture::FaceInfo& first_face = face_infos_[0];
1067 const Texture::LevelInfo& first_level = first_face.level_infos[0];
1068 const GLsizei levels_needed = first_face.num_mip_levels;
1070 texture_complete_ =
1071 max_level_set_ >= (levels_needed - 1) && max_level_set_ >= 0;
1072 cube_complete_ = (face_infos_.size() == 6) &&
1073 (first_level.width == first_level.height);
1075 if (first_level.width == 0 || first_level.height == 0) {
1076 texture_complete_ = false;
1077 } else if (first_level.type == GL_FLOAT &&
1078 !feature_info->feature_flags().enable_texture_float_linear &&
1079 (min_filter_ != GL_NEAREST_MIPMAP_NEAREST ||
1080 mag_filter_ != GL_NEAREST)) {
1081 texture_complete_ = false;
1082 } else if (first_level.type == GL_HALF_FLOAT_OES &&
1083 !feature_info->feature_flags().enable_texture_half_float_linear &&
1084 (min_filter_ != GL_NEAREST_MIPMAP_NEAREST ||
1085 mag_filter_ != GL_NEAREST)) {
1086 texture_complete_ = false;
1089 if (cube_complete_ && texture_level0_dirty_) {
1090 texture_level0_complete_ = true;
1091 for (size_t ii = 0; ii < face_infos_.size(); ++ii) {
1092 const Texture::LevelInfo& level0 = face_infos_[ii].level_infos[0];
1093 if (!TextureFaceComplete(first_level,
1095 level0.target,
1096 level0.internal_format,
1097 level0.width,
1098 level0.height,
1099 level0.depth,
1100 level0.format,
1101 level0.type)) {
1102 texture_level0_complete_ = false;
1103 break;
1106 texture_level0_dirty_ = false;
1108 cube_complete_ &= texture_level0_complete_;
1110 if (texture_complete_ && texture_mips_dirty_) {
1111 texture_mips_complete_ = true;
1112 for (size_t ii = 0;
1113 ii < face_infos_.size() && texture_mips_complete_;
1114 ++ii) {
1115 const Texture::FaceInfo& face_info = face_infos_[ii];
1116 const Texture::LevelInfo& level0 = face_info.level_infos[0];
1117 for (GLsizei jj = 1; jj < levels_needed; ++jj) {
1118 const Texture::LevelInfo& level_info = face_infos_[ii].level_infos[jj];
1119 if (!TextureMipComplete(level0,
1120 level_info.target,
1122 level_info.internal_format,
1123 level_info.width,
1124 level_info.height,
1125 level_info.depth,
1126 level_info.format,
1127 level_info.type)) {
1128 texture_mips_complete_ = false;
1129 break;
1133 texture_mips_dirty_ = false;
1135 texture_complete_ &= texture_mips_complete_;
1138 bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) {
1139 DCHECK(decoder);
1140 if (cleared_) {
1141 return true;
1144 for (size_t ii = 0; ii < face_infos_.size(); ++ii) {
1145 const Texture::FaceInfo& face_info = face_infos_[ii];
1146 for (GLint jj = 0; jj < face_info.num_mip_levels; ++jj) {
1147 const Texture::LevelInfo& info = face_info.level_infos[jj];
1148 if (info.target != 0) {
1149 if (!ClearLevel(decoder, info.target, jj)) {
1150 return false;
1155 UpdateSafeToRenderFrom(true);
1156 return true;
1159 gfx::Rect Texture::GetLevelClearedRect(GLenum target, GLint level) const {
1160 size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
1161 if (face_index >= face_infos_.size() ||
1162 level >= static_cast<GLint>(face_infos_[face_index].level_infos.size())) {
1163 return gfx::Rect();
1166 const Texture::LevelInfo& info = face_infos_[face_index].level_infos[level];
1168 return info.cleared_rect;
1171 bool Texture::IsLevelCleared(GLenum target, GLint level) const {
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 const Texture::LevelInfo& info = face_infos_[face_index].level_infos[level];
1180 return info.cleared_rect == gfx::Rect(info.width, info.height);
1183 void Texture::InitTextureMaxAnisotropyIfNeeded(GLenum target) {
1184 if (texture_max_anisotropy_initialized_)
1185 return;
1186 texture_max_anisotropy_initialized_ = true;
1187 GLfloat params[] = { 1.0f };
1188 glTexParameterfv(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, params);
1191 bool Texture::ClearLevel(
1192 GLES2Decoder* decoder, GLenum target, GLint level) {
1193 DCHECK(decoder);
1194 size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
1195 if (face_index >= face_infos_.size() ||
1196 level >= static_cast<GLint>(face_infos_[face_index].level_infos.size())) {
1197 return true;
1200 Texture::LevelInfo& info = face_infos_[face_index].level_infos[level];
1202 DCHECK(target == info.target);
1204 if (info.target == 0 ||
1205 info.cleared_rect == gfx::Rect(info.width, info.height) ||
1206 info.width == 0 || info.height == 0 || info.depth == 0) {
1207 return true;
1210 // Clear all remaining sub regions.
1211 const int x[] = {
1212 0, info.cleared_rect.x(), info.cleared_rect.right(), info.width};
1213 const int y[] = {
1214 0, info.cleared_rect.y(), info.cleared_rect.bottom(), info.height};
1216 for (size_t j = 0; j < 3; ++j) {
1217 for (size_t i = 0; i < 3; ++i) {
1218 // Center of nine patch is already cleared.
1219 if (j == 1 && i == 1)
1220 continue;
1222 gfx::Rect rect(x[i], y[j], x[i + 1] - x[i], y[j + 1] - y[j]);
1223 if (rect.IsEmpty())
1224 continue;
1226 // NOTE: It seems kind of gross to call back into the decoder for this
1227 // but only the decoder knows all the state (like unpack_alignment_)
1228 // that's needed to be able to call GL correctly.
1229 bool cleared = decoder->ClearLevel(this, info.target, info.level,
1230 info.format, info.type, rect.x(),
1231 rect.y(), rect.width(), rect.height());
1232 if (!cleared)
1233 return false;
1237 UpdateMipCleared(&info, info.width, info.height,
1238 gfx::Rect(info.width, info.height));
1239 return true;
1242 void Texture::SetLevelImage(
1243 const FeatureInfo* feature_info,
1244 GLenum target,
1245 GLint level,
1246 gfx::GLImage* image) {
1247 DCHECK_GE(level, 0);
1248 size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
1249 DCHECK_LT(static_cast<size_t>(face_index),
1250 face_infos_.size());
1251 DCHECK_LT(static_cast<size_t>(level),
1252 face_infos_[face_index].level_infos.size());
1253 Texture::LevelInfo& info =
1254 face_infos_[face_index].level_infos[level];
1255 DCHECK_EQ(info.target, target);
1256 DCHECK_EQ(info.level, level);
1257 info.image = image;
1258 UpdateCanRenderCondition();
1259 UpdateHasImages();
1262 gfx::GLImage* Texture::GetLevelImage(GLint target, GLint level) const {
1263 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES &&
1264 target != GL_TEXTURE_RECTANGLE_ARB) {
1265 return NULL;
1268 size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
1269 if (level >= 0 && face_index < face_infos_.size() &&
1270 static_cast<size_t>(level) < face_infos_[face_index].level_infos.size()) {
1271 const LevelInfo& info = face_infos_[face_index].level_infos[level];
1272 if (info.target != 0) {
1273 return info.image.get();
1276 return NULL;
1279 void Texture::OnWillModifyPixels() {
1280 gfx::GLImage* image = GetLevelImage(target(), 0);
1281 if (image)
1282 image->WillModifyTexImage();
1285 void Texture::OnDidModifyPixels() {
1286 gfx::GLImage* image = GetLevelImage(target(), 0);
1287 if (image)
1288 image->DidModifyTexImage();
1291 TextureRef::TextureRef(TextureManager* manager,
1292 GLuint client_id,
1293 Texture* texture)
1294 : manager_(manager),
1295 texture_(texture),
1296 client_id_(client_id),
1297 num_observers_(0) {
1298 DCHECK(manager_);
1299 DCHECK(texture_);
1300 texture_->AddTextureRef(this);
1301 manager_->StartTracking(this);
1304 scoped_refptr<TextureRef> TextureRef::Create(TextureManager* manager,
1305 GLuint client_id,
1306 GLuint service_id) {
1307 return new TextureRef(manager, client_id, new Texture(service_id));
1310 TextureRef::~TextureRef() {
1311 manager_->StopTracking(this);
1312 texture_->RemoveTextureRef(this, manager_->have_context_);
1313 manager_ = NULL;
1316 TextureManager::TextureManager(MemoryTracker* memory_tracker,
1317 FeatureInfo* feature_info,
1318 GLint max_texture_size,
1319 GLint max_cube_map_texture_size,
1320 GLint max_rectangle_texture_size,
1321 GLint max_3d_texture_size,
1322 bool use_default_textures)
1323 : memory_tracker_managed_(
1324 new MemoryTypeTracker(memory_tracker, MemoryTracker::kManaged)),
1325 memory_tracker_unmanaged_(
1326 new MemoryTypeTracker(memory_tracker, MemoryTracker::kUnmanaged)),
1327 feature_info_(feature_info),
1328 framebuffer_manager_(NULL),
1329 max_texture_size_(max_texture_size),
1330 max_cube_map_texture_size_(max_cube_map_texture_size),
1331 max_rectangle_texture_size_(max_rectangle_texture_size),
1332 max_3d_texture_size_(max_3d_texture_size),
1333 max_levels_(ComputeMipMapCount(GL_TEXTURE_2D,
1334 max_texture_size,
1335 max_texture_size,
1336 max_texture_size)),
1337 max_cube_map_levels_(ComputeMipMapCount(GL_TEXTURE_CUBE_MAP,
1338 max_cube_map_texture_size,
1339 max_cube_map_texture_size,
1340 max_cube_map_texture_size)),
1341 max_3d_levels_(ComputeMipMapCount(GL_TEXTURE_3D,
1342 // Same as GL_TEXTURE_2D_ARRAY
1343 max_3d_texture_size,
1344 max_3d_texture_size,
1345 max_3d_texture_size)),
1346 use_default_textures_(use_default_textures),
1347 num_unrenderable_textures_(0),
1348 num_unsafe_textures_(0),
1349 num_uncleared_mips_(0),
1350 num_images_(0),
1351 texture_count_(0),
1352 have_context_(true) {
1353 for (int ii = 0; ii < kNumDefaultTextures; ++ii) {
1354 black_texture_ids_[ii] = 0;
1358 bool TextureManager::Initialize() {
1359 // TODO(gman): The default textures have to be real textures, not the 0
1360 // texture because we simulate non shared resources on top of shared
1361 // resources and all contexts that share resource share the same default
1362 // texture.
1363 default_textures_[kTexture2D] = CreateDefaultAndBlackTextures(
1364 GL_TEXTURE_2D, &black_texture_ids_[kTexture2D]);
1365 default_textures_[kCubeMap] = CreateDefaultAndBlackTextures(
1366 GL_TEXTURE_CUBE_MAP, &black_texture_ids_[kCubeMap]);
1368 if (feature_info_->feature_flags().oes_egl_image_external) {
1369 default_textures_[kExternalOES] = CreateDefaultAndBlackTextures(
1370 GL_TEXTURE_EXTERNAL_OES, &black_texture_ids_[kExternalOES]);
1373 if (feature_info_->feature_flags().arb_texture_rectangle) {
1374 default_textures_[kRectangleARB] = CreateDefaultAndBlackTextures(
1375 GL_TEXTURE_RECTANGLE_ARB, &black_texture_ids_[kRectangleARB]);
1378 return true;
1381 scoped_refptr<TextureRef>
1382 TextureManager::CreateDefaultAndBlackTextures(
1383 GLenum target,
1384 GLuint* black_texture) {
1385 static uint8 black[] = {0, 0, 0, 255};
1387 // Sampling a texture not associated with any EGLImage sibling will return
1388 // black values according to the spec.
1389 bool needs_initialization = (target != GL_TEXTURE_EXTERNAL_OES);
1390 bool needs_faces = (target == GL_TEXTURE_CUBE_MAP);
1392 // Make default textures and texture for replacing non-renderable textures.
1393 GLuint ids[2];
1394 const int num_ids = use_default_textures_ ? 2 : 1;
1395 glGenTextures(num_ids, ids);
1396 for (int ii = 0; ii < num_ids; ++ii) {
1397 glBindTexture(target, ids[ii]);
1398 if (needs_initialization) {
1399 if (needs_faces) {
1400 for (int jj = 0; jj < GLES2Util::kNumFaces; ++jj) {
1401 glTexImage2D(GLES2Util::IndexToGLFaceTarget(jj), 0, GL_RGBA, 1, 1, 0,
1402 GL_RGBA, GL_UNSIGNED_BYTE, black);
1404 } else {
1405 glTexImage2D(target, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
1406 GL_UNSIGNED_BYTE, black);
1410 glBindTexture(target, 0);
1412 scoped_refptr<TextureRef> default_texture;
1413 if (use_default_textures_) {
1414 default_texture = TextureRef::Create(this, 0, ids[1]);
1415 SetTarget(default_texture.get(), target);
1416 if (needs_faces) {
1417 for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) {
1418 SetLevelInfo(default_texture.get(), GLES2Util::IndexToGLFaceTarget(ii),
1419 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1420 gfx::Rect(1, 1));
1422 } else {
1423 if (needs_initialization) {
1424 SetLevelInfo(default_texture.get(), GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1,
1425 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(1, 1));
1426 } else {
1427 SetLevelInfo(default_texture.get(), GL_TEXTURE_EXTERNAL_OES, 0, GL_RGBA,
1428 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(1, 1));
1433 *black_texture = ids[0];
1434 return default_texture;
1437 bool TextureManager::ValidForTarget(
1438 GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth) {
1439 GLsizei max_size = MaxSizeForTarget(target) >> level;
1440 return level >= 0 &&
1441 width >= 0 &&
1442 height >= 0 &&
1443 depth >= 0 &&
1444 level < MaxLevelsForTarget(target) &&
1445 width <= max_size &&
1446 height <= max_size &&
1447 depth <= max_size &&
1448 (level == 0 || feature_info_->feature_flags().npot_ok ||
1449 (!GLES2Util::IsNPOT(width) &&
1450 !GLES2Util::IsNPOT(height) &&
1451 !GLES2Util::IsNPOT(depth))) &&
1452 (target != GL_TEXTURE_CUBE_MAP || (width == height && depth == 1)) &&
1453 (target != GL_TEXTURE_2D || (depth == 1));
1456 void TextureManager::SetTarget(TextureRef* ref, GLenum target) {
1457 DCHECK(ref);
1458 ref->texture()
1459 ->SetTarget(feature_info_.get(), target, MaxLevelsForTarget(target));
1462 void TextureManager::SetLevelClearedRect(TextureRef* ref,
1463 GLenum target,
1464 GLint level,
1465 const gfx::Rect& cleared_rect) {
1466 DCHECK(ref);
1467 ref->texture()->SetLevelClearedRect(target, level, cleared_rect);
1470 void TextureManager::SetLevelCleared(TextureRef* ref,
1471 GLenum target,
1472 GLint level,
1473 bool cleared) {
1474 DCHECK(ref);
1475 ref->texture()->SetLevelCleared(target, level, cleared);
1478 bool TextureManager::ClearRenderableLevels(
1479 GLES2Decoder* decoder, TextureRef* ref) {
1480 DCHECK(ref);
1481 return ref->texture()->ClearRenderableLevels(decoder);
1484 bool TextureManager::ClearTextureLevel(
1485 GLES2Decoder* decoder, TextureRef* ref,
1486 GLenum target, GLint level) {
1487 DCHECK(ref);
1488 Texture* texture = ref->texture();
1489 if (texture->num_uncleared_mips() == 0) {
1490 return true;
1492 bool result = texture->ClearLevel(decoder, target, level);
1493 texture->UpdateCleared();
1494 return result;
1497 void TextureManager::SetLevelInfo(TextureRef* ref,
1498 GLenum target,
1499 GLint level,
1500 GLenum internal_format,
1501 GLsizei width,
1502 GLsizei height,
1503 GLsizei depth,
1504 GLint border,
1505 GLenum format,
1506 GLenum type,
1507 const gfx::Rect& cleared_rect) {
1508 DCHECK(gfx::Rect(width, height).Contains(cleared_rect));
1509 DCHECK(ref);
1510 Texture* texture = ref->texture();
1512 texture->GetMemTracker()->TrackMemFree(texture->estimated_size());
1513 texture->SetLevelInfo(feature_info_.get(), target, level, internal_format,
1514 width, height, depth, border, format, type,
1515 cleared_rect);
1516 texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size());
1519 Texture* TextureManager::Produce(TextureRef* ref) {
1520 DCHECK(ref);
1521 return ref->texture();
1524 TextureRef* TextureManager::Consume(
1525 GLuint client_id,
1526 Texture* texture) {
1527 DCHECK(client_id);
1528 scoped_refptr<TextureRef> ref(new TextureRef(this, client_id, texture));
1529 bool result = textures_.insert(std::make_pair(client_id, ref)).second;
1530 DCHECK(result);
1531 return ref.get();
1534 void TextureManager::SetParameteri(
1535 const char* function_name, ErrorState* error_state,
1536 TextureRef* ref, GLenum pname, GLint param) {
1537 DCHECK(error_state);
1538 DCHECK(ref);
1539 Texture* texture = ref->texture();
1540 GLenum result = texture->SetParameteri(feature_info_.get(), pname, param);
1541 if (result != GL_NO_ERROR) {
1542 if (result == GL_INVALID_ENUM) {
1543 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1544 error_state, function_name, param, "param");
1545 } else {
1546 ERRORSTATE_SET_GL_ERROR_INVALID_PARAMI(
1547 error_state, result, function_name, pname, param);
1549 } else {
1550 // Texture tracking pools exist only for the command decoder, so
1551 // do not pass them on to the native GL implementation.
1552 if (pname != GL_TEXTURE_POOL_CHROMIUM) {
1553 glTexParameteri(texture->target(), pname, param);
1558 void TextureManager::SetParameterf(
1559 const char* function_name, ErrorState* error_state,
1560 TextureRef* ref, GLenum pname, GLfloat param) {
1561 DCHECK(error_state);
1562 DCHECK(ref);
1563 Texture* texture = ref->texture();
1564 GLenum result = texture->SetParameterf(feature_info_.get(), pname, param);
1565 if (result != GL_NO_ERROR) {
1566 if (result == GL_INVALID_ENUM) {
1567 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1568 error_state, function_name, pname, "pname");
1569 } else {
1570 ERRORSTATE_SET_GL_ERROR_INVALID_PARAMF(
1571 error_state, result, function_name, pname, param);
1573 } else {
1574 // Texture tracking pools exist only for the command decoder, so
1575 // do not pass them on to the native GL implementation.
1576 if (pname != GL_TEXTURE_POOL_CHROMIUM) {
1577 glTexParameterf(texture->target(), pname, param);
1582 bool TextureManager::MarkMipmapsGenerated(TextureRef* ref) {
1583 DCHECK(ref);
1584 Texture* texture = ref->texture();
1585 texture->GetMemTracker()->TrackMemFree(texture->estimated_size());
1586 bool result = texture->MarkMipmapsGenerated(feature_info_.get());
1587 texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size());
1588 return result;
1591 TextureRef* TextureManager::CreateTexture(
1592 GLuint client_id, GLuint service_id) {
1593 DCHECK_NE(0u, service_id);
1594 scoped_refptr<TextureRef> ref(TextureRef::Create(
1595 this, client_id, service_id));
1596 std::pair<TextureMap::iterator, bool> result =
1597 textures_.insert(std::make_pair(client_id, ref));
1598 DCHECK(result.second);
1599 return ref.get();
1602 TextureRef* TextureManager::GetTexture(
1603 GLuint client_id) const {
1604 TextureMap::const_iterator it = textures_.find(client_id);
1605 return it != textures_.end() ? it->second.get() : NULL;
1608 void TextureManager::RemoveTexture(GLuint client_id) {
1609 TextureMap::iterator it = textures_.find(client_id);
1610 if (it != textures_.end()) {
1611 it->second->reset_client_id();
1612 textures_.erase(it);
1616 void TextureManager::StartTracking(TextureRef* ref) {
1617 Texture* texture = ref->texture();
1618 ++texture_count_;
1619 num_uncleared_mips_ += texture->num_uncleared_mips();
1620 if (!texture->SafeToRenderFrom())
1621 ++num_unsafe_textures_;
1622 if (!texture->CanRender(feature_info_.get()))
1623 ++num_unrenderable_textures_;
1624 if (texture->HasImages())
1625 ++num_images_;
1628 void TextureManager::StopTracking(TextureRef* ref) {
1629 if (ref->num_observers()) {
1630 for (unsigned int i = 0; i < destruction_observers_.size(); i++) {
1631 destruction_observers_[i]->OnTextureRefDestroying(ref);
1633 DCHECK_EQ(ref->num_observers(), 0);
1636 Texture* texture = ref->texture();
1638 --texture_count_;
1639 if (texture->HasImages()) {
1640 DCHECK_NE(0, num_images_);
1641 --num_images_;
1643 if (!texture->CanRender(feature_info_.get())) {
1644 DCHECK_NE(0, num_unrenderable_textures_);
1645 --num_unrenderable_textures_;
1647 if (!texture->SafeToRenderFrom()) {
1648 DCHECK_NE(0, num_unsafe_textures_);
1649 --num_unsafe_textures_;
1651 num_uncleared_mips_ -= texture->num_uncleared_mips();
1652 DCHECK_GE(num_uncleared_mips_, 0);
1655 MemoryTypeTracker* TextureManager::GetMemTracker(GLenum tracking_pool) {
1656 switch (tracking_pool) {
1657 case GL_TEXTURE_POOL_MANAGED_CHROMIUM:
1658 return memory_tracker_managed_.get();
1659 break;
1660 case GL_TEXTURE_POOL_UNMANAGED_CHROMIUM:
1661 return memory_tracker_unmanaged_.get();
1662 break;
1663 default:
1664 break;
1666 NOTREACHED();
1667 return NULL;
1670 Texture* TextureManager::GetTextureForServiceId(GLuint service_id) const {
1671 // This doesn't need to be fast. It's only used during slow queries.
1672 for (TextureMap::const_iterator it = textures_.begin();
1673 it != textures_.end(); ++it) {
1674 Texture* texture = it->second->texture();
1675 if (texture->service_id() == service_id)
1676 return texture;
1678 return NULL;
1681 GLsizei TextureManager::ComputeMipMapCount(GLenum target,
1682 GLsizei width,
1683 GLsizei height,
1684 GLsizei depth) {
1685 switch (target) {
1686 case GL_TEXTURE_EXTERNAL_OES:
1687 return 1;
1688 default:
1689 return 1 +
1690 base::bits::Log2Floor(std::max(std::max(width, height), depth));
1694 void TextureManager::SetLevelImage(
1695 TextureRef* ref,
1696 GLenum target,
1697 GLint level,
1698 gfx::GLImage* image) {
1699 DCHECK(ref);
1700 ref->texture()->SetLevelImage(feature_info_.get(), target, level, image);
1703 size_t TextureManager::GetSignatureSize() const {
1704 return sizeof(TextureTag) + sizeof(TextureSignature);
1707 void TextureManager::AddToSignature(
1708 TextureRef* ref,
1709 GLenum target,
1710 GLint level,
1711 std::string* signature) const {
1712 ref->texture()->AddToSignature(feature_info_.get(), target, level, signature);
1715 void TextureManager::UpdateSafeToRenderFrom(int delta) {
1716 num_unsafe_textures_ += delta;
1717 DCHECK_GE(num_unsafe_textures_, 0);
1720 void TextureManager::UpdateUnclearedMips(int delta) {
1721 num_uncleared_mips_ += delta;
1722 DCHECK_GE(num_uncleared_mips_, 0);
1725 void TextureManager::UpdateCanRenderCondition(
1726 Texture::CanRenderCondition old_condition,
1727 Texture::CanRenderCondition new_condition) {
1728 if (old_condition == Texture::CAN_RENDER_NEVER ||
1729 (old_condition == Texture::CAN_RENDER_ONLY_IF_NPOT &&
1730 !feature_info_->feature_flags().npot_ok)) {
1731 DCHECK_GT(num_unrenderable_textures_, 0);
1732 --num_unrenderable_textures_;
1734 if (new_condition == Texture::CAN_RENDER_NEVER ||
1735 (new_condition == Texture::CAN_RENDER_ONLY_IF_NPOT &&
1736 !feature_info_->feature_flags().npot_ok))
1737 ++num_unrenderable_textures_;
1740 void TextureManager::UpdateNumImages(int delta) {
1741 num_images_ += delta;
1742 DCHECK_GE(num_images_, 0);
1745 void TextureManager::IncFramebufferStateChangeCount() {
1746 if (framebuffer_manager_)
1747 framebuffer_manager_->IncFramebufferStateChangeCount();
1750 bool TextureManager::ValidateFormatAndTypeCombination(
1751 ErrorState* error_state, const char* function_name, GLenum format,
1752 GLenum type) {
1753 // TODO(zmo): now this is only called by GLES2DecoderImpl::DoCopyTexImage2D
1754 // and is incorrect for ES3. Fix this.
1755 if (!g_format_type_validator.Get().IsValid(format, format, type)) {
1756 ERRORSTATE_SET_GL_ERROR(
1757 error_state, GL_INVALID_OPERATION, function_name,
1758 (std::string("invalid type ") +
1759 GLES2Util::GetStringEnum(type) + " for format " +
1760 GLES2Util::GetStringEnum(format)).c_str());
1761 return false;
1763 return true;
1766 bool TextureManager::ValidateTextureParameters(
1767 ErrorState* error_state, const char* function_name,
1768 GLenum format, GLenum type, GLenum internal_format, GLint level) {
1769 const Validators* validators = feature_info_->validators();
1770 if (!validators->texture_format.IsValid(format)) {
1771 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1772 error_state, function_name, format, "format");
1773 return false;
1775 if (!validators->pixel_type.IsValid(type)) {
1776 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1777 error_state, function_name, type, "type");
1778 return false;
1780 if (!g_format_type_validator.Get().IsValid(internal_format, format, type)) {
1781 ERRORSTATE_SET_GL_ERROR(
1782 error_state, GL_INVALID_OPERATION, function_name,
1783 "invalid internalformat/format/type combination");
1784 return false;
1786 // For TexSubImage calls, internal_format isn't part of the parameters,
1787 // so its validation needs to be after the internal_format/format/type
1788 // combination validation. Otherwise, an unexpected INVALID_ENUM could be
1789 // generated instead of INVALID_OPERATION.
1790 if (!validators->texture_internal_format.IsValid(internal_format)) {
1791 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1792 error_state, function_name, internal_format, "internal_format");
1793 return false;
1795 if (!feature_info_->IsES3Enabled()) {
1796 uint32 channels = GLES2Util::GetChannelsForFormat(format);
1797 if ((channels & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && level) {
1798 ERRORSTATE_SET_GL_ERROR(
1799 error_state, GL_INVALID_OPERATION, function_name,
1800 (std::string("invalid format ") + GLES2Util::GetStringEnum(format) +
1801 " for level != 0").c_str());
1802 return false;
1805 return true;
1808 // Gets the texture id for a given target.
1809 TextureRef* TextureManager::GetTextureInfoForTarget(
1810 ContextState* state, GLenum target) {
1811 TextureUnit& unit = state->texture_units[state->active_texture_unit];
1812 TextureRef* texture = NULL;
1813 switch (target) {
1814 case GL_TEXTURE_2D:
1815 texture = unit.bound_texture_2d.get();
1816 break;
1817 case GL_TEXTURE_CUBE_MAP:
1818 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1819 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1820 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1821 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1822 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1823 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1824 texture = unit.bound_texture_cube_map.get();
1825 break;
1826 case GL_TEXTURE_EXTERNAL_OES:
1827 texture = unit.bound_texture_external_oes.get();
1828 break;
1829 case GL_TEXTURE_RECTANGLE_ARB:
1830 texture = unit.bound_texture_rectangle_arb.get();
1831 break;
1832 case GL_TEXTURE_3D:
1833 texture = unit.bound_texture_3d.get();
1834 break;
1835 case GL_TEXTURE_2D_ARRAY:
1836 texture = unit.bound_texture_2d_array.get();
1837 break;
1838 default:
1839 NOTREACHED();
1840 return NULL;
1842 return texture;
1845 TextureRef* TextureManager::GetTextureInfoForTargetUnlessDefault(
1846 ContextState* state, GLenum target) {
1847 TextureRef* texture = GetTextureInfoForTarget(state, target);
1848 if (!texture)
1849 return NULL;
1850 if (texture == GetDefaultTextureInfo(target))
1851 return NULL;
1852 return texture;
1855 bool TextureManager::ValidateTexImage(
1856 ContextState* state,
1857 const char* function_name,
1858 const DoTexImageArguments& args,
1859 TextureRef** texture_ref) {
1860 ErrorState* error_state = state->GetErrorState();
1861 const Validators* validators = feature_info_->validators();
1862 if (((args.command_type == DoTexImageArguments::kTexImage2D) &&
1863 !validators->texture_target.IsValid(args.target)) ||
1864 ((args.command_type == DoTexImageArguments::kTexImage3D) &&
1865 !validators->texture_3_d_target.IsValid(args.target))) {
1866 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1867 error_state, function_name, args.target, "target");
1868 return false;
1870 if (!ValidateTextureParameters(
1871 error_state, function_name, args.format, args.type,
1872 args.internal_format, args.level)) {
1873 return false;
1875 if (!ValidForTarget(args.target, args.level,
1876 args.width, args.height, args.depth) ||
1877 args.border != 0) {
1878 ERRORSTATE_SET_GL_ERROR(
1879 error_state, GL_INVALID_VALUE, function_name,
1880 "dimensions out of range");
1881 return false;
1883 if ((GLES2Util::GetChannelsForFormat(args.format) &
1884 (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && args.pixels) {
1885 ERRORSTATE_SET_GL_ERROR(
1886 error_state, GL_INVALID_OPERATION,
1887 function_name, "can not supply data for depth or stencil textures");
1888 return false;
1891 TextureRef* local_texture_ref = GetTextureInfoForTarget(state, args.target);
1892 if (!local_texture_ref) {
1893 ERRORSTATE_SET_GL_ERROR(
1894 error_state, GL_INVALID_OPERATION, function_name,
1895 "unknown texture for target");
1896 return false;
1898 if (local_texture_ref->texture()->IsImmutable()) {
1899 ERRORSTATE_SET_GL_ERROR(
1900 error_state, GL_INVALID_OPERATION, function_name,
1901 "texture is immutable");
1902 return false;
1905 if (!memory_tracker_managed_->EnsureGPUMemoryAvailable(args.pixels_size)) {
1906 ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, function_name,
1907 "out of memory");
1908 return false;
1911 // Write the TextureReference since this is valid.
1912 *texture_ref = local_texture_ref;
1913 return true;
1916 void TextureManager::ValidateAndDoTexImage(
1917 DecoderTextureState* texture_state,
1918 ContextState* state,
1919 DecoderFramebufferState* framebuffer_state,
1920 const char* function_name,
1921 const DoTexImageArguments& args) {
1922 TextureRef* texture_ref;
1923 if (!ValidateTexImage(state, function_name, args, &texture_ref)) {
1924 return;
1927 DoTexImage(texture_state, state->GetErrorState(), framebuffer_state,
1928 function_name, texture_ref, args);
1931 GLenum TextureManager::AdjustTexFormat(GLenum format) const {
1932 // TODO(bajones): GLES 3 allows for internal format and format to differ.
1933 // This logic may need to change as a result.
1934 if (gfx::GetGLImplementation() == gfx::kGLImplementationDesktopGL) {
1935 if (format == GL_SRGB_EXT)
1936 return GL_RGB;
1937 if (format == GL_SRGB_ALPHA_EXT)
1938 return GL_RGBA;
1940 return format;
1943 void TextureManager::DoTexImage(
1944 DecoderTextureState* texture_state,
1945 ErrorState* error_state,
1946 DecoderFramebufferState* framebuffer_state,
1947 const char* function_name,
1948 TextureRef* texture_ref,
1949 const DoTexImageArguments& args) {
1950 Texture* texture = texture_ref->texture();
1951 GLsizei tex_width = 0;
1952 GLsizei tex_height = 0;
1953 GLsizei tex_depth = 0;
1954 GLenum tex_type = 0;
1955 GLenum tex_format = 0;
1956 bool level_is_same =
1957 texture->GetLevelSize(
1958 args.target, args.level, &tex_width, &tex_height, &tex_depth) &&
1959 texture->GetLevelType(args.target, args.level, &tex_type, &tex_format) &&
1960 args.width == tex_width && args.height == tex_height &&
1961 args.depth == tex_depth && args.type == tex_type &&
1962 args.format == tex_format;
1964 if (level_is_same && !args.pixels) {
1965 // Just set the level texture but mark the texture as uncleared.
1966 SetLevelInfo(texture_ref, args.target, args.level, args.internal_format,
1967 args.width, args.height, args.depth, args.border, args.format,
1968 args.type, gfx::Rect());
1969 texture_state->tex_image_failed = false;
1970 return;
1973 if (texture->IsAttachedToFramebuffer()) {
1974 framebuffer_state->clear_state_dirty = true;
1977 if (texture_state->texsubimage_faster_than_teximage &&
1978 level_is_same && args.pixels) {
1980 ScopedTextureUploadTimer timer(texture_state);
1981 if (args.command_type == DoTexImageArguments::kTexImage3D) {
1982 glTexSubImage3D(args.target, args.level, 0, 0, 0,
1983 args.width, args.height, args.depth,
1984 args.format, args.type, args.pixels);
1985 } else {
1986 glTexSubImage2D(args.target, args.level, 0, 0, args.width, args.height,
1987 AdjustTexFormat(args.format), args.type, args.pixels);
1990 SetLevelCleared(texture_ref, args.target, args.level, true);
1991 texture_state->tex_image_failed = false;
1992 return;
1995 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, function_name);
1997 ScopedTextureUploadTimer timer(texture_state);
1998 if (args.command_type == DoTexImageArguments::kTexImage3D) {
1999 glTexImage3D(args.target, args.level, args.internal_format, args.width,
2000 args.height, args.depth, args.border, args.format,
2001 args.type, args.pixels);
2002 } else {
2003 glTexImage2D(args.target, args.level, args.internal_format, args.width,
2004 args.height, args.border, AdjustTexFormat(args.format),
2005 args.type, args.pixels);
2008 GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, function_name);
2009 if (error == GL_NO_ERROR) {
2010 SetLevelInfo(
2011 texture_ref, args.target, args.level, args.internal_format, args.width,
2012 args.height, args.depth, args.border, args.format, args.type,
2013 args.pixels != NULL ? gfx::Rect(args.width, args.height) : gfx::Rect());
2014 texture_state->tex_image_failed = false;
2018 ScopedTextureUploadTimer::ScopedTextureUploadTimer(
2019 DecoderTextureState* texture_state)
2020 : texture_state_(texture_state),
2021 begin_time_(base::TimeTicks::Now()) {
2024 ScopedTextureUploadTimer::~ScopedTextureUploadTimer() {
2025 texture_state_->texture_upload_count++;
2026 texture_state_->total_texture_upload_time +=
2027 base::TimeTicks::Now() - begin_time_;
2030 } // namespace gles2
2031 } // namespace gpu