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"
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"
29 // This should contain everything to uniquely identify a Texture.
30 const char TextureTag
[] = "|Texture|";
31 struct TextureSignature
{
40 GLenum internal_format_
;
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
,
70 GLenum internal_format
,
87 memset(this, 0, sizeof(TextureSignature
));
90 min_filter_
= min_filter
;
91 mag_filter_
= mag_filter
;
96 internal_format_
= internal_format
;
97 compare_func_
= compare_func
;
98 compare_mode_
= compare_mode
;
104 base_level_
= base_level
;
106 max_level_
= max_level
;
109 has_image_
= has_image
;
110 can_render_
= can_render
;
111 can_render_to_
= can_render_to
;
116 class FormatTypeValidator
{
118 FormatTypeValidator() {
119 static const FormatType kSupportedFormatTypes
[] = {
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
},
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();
240 // TODO(zmo): once std::tuple is allowed, switch over to that.
242 GLenum internal_format
;
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
;
291 for (int ii
= 0; ii
< kNumDefaultTextures
; ++ii
) {
292 default_textures_
[ii
] = NULL
;
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
),
308 num_uncleared_mips_(0),
311 min_filter_(GL_NEAREST_MIPMAP_LINEAR
),
312 mag_filter_(GL_LINEAR
),
317 pool_(GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
),
318 compare_func_(GL_LEQUAL
),
319 compare_mode_(GL_NONE
),
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),
332 has_been_bound_(false),
333 framebuffer_attachment_count_(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());
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);
364 GLuint id
= service_id();
365 glDeleteTextures(1, &id
);
368 } else if (memory_tracking_ref_
== NULL
) {
369 // TODO(piman): tune ownership semantics for cross-context group shared
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()
395 Texture::LevelInfo::LevelInfo(const LevelInfo
& rhs
)
396 : cleared(rhs
.cleared
),
399 internal_format(rhs
.internal_format
),
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 {
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();
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
;
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
:
463 case CAN_RENDER_NEVER
:
465 case CAN_RENDER_ONLY_IF_NPOT
:
468 return feature_info
->feature_flags().npot_ok
;
471 void Texture::AddToSignature(
472 const FeatureInfo
* feature_info
,
475 std::string
* signature
) const {
476 DCHECK(feature_info
);
479 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
480 DCHECK_LT(static_cast<size_t>(face_index
),
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
,
496 info
.internal_format
,
509 info
.image
.get() != NULL
,
510 CanRender(feature_info
),
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
)) {
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
,
546 level0_info
.internal_format
,
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.
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
) {
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
) {
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
)) {
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
) ||
615 bool Texture::TextureIsNPOT(GLsizei width
,
618 return (GLES2Util::IsNPOT(width
) ||
619 GLES2Util::IsNPOT(height
) ||
620 GLES2Util::IsNPOT(depth
));
623 bool Texture::TextureFaceComplete(const Texture::LevelInfo
& first_face
,
626 GLenum internal_format
,
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
);
643 bool Texture::TextureMipComplete(const Texture::LevelInfo
& level0_face
,
646 GLenum internal_format
,
652 bool complete
= (target
!= 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
);
668 void Texture::SetLevelCleared(GLenum target
, GLint level
, bool cleared
) {
670 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
671 DCHECK_LT(static_cast<size_t>(face_index
),
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
);
681 void Texture::UpdateCleared() {
682 if (face_infos_
.empty()) {
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
)
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
)
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
)
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())
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
) {
741 if (has_images_
== has_images
)
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
,
758 GLenum internal_format
,
767 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
768 DCHECK_LT(static_cast<size_t>(face_index
),
770 DCHECK_LT(static_cast<size_t>(level
),
771 face_infos_
[face_index
].level_infos
.size());
773 DCHECK_GE(height
, 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
||
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
;
809 info
.internal_format
= internal_format
;
811 info
.height
= height
;
813 info
.border
= border
;
814 info
.format
= format
;
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
);
827 UpdateCanRenderCondition();
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(
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
];
853 return SafeAddInt32(xoffset
, width
, &max_x
) &&
854 SafeAddInt32(yoffset
, height
, &max_y
) &&
855 SafeAddInt32(zoffset
, depth
, &max_z
) &&
859 max_x
<= info
.width
&&
860 max_y
<= info
.height
&&
861 max_z
<= info
.depth
&&
867 bool Texture::GetLevelSize(
868 GLint target
, GLint level
,
869 GLsizei
* width
, GLsizei
* height
, GLsizei
* depth
) const {
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) {
878 *height
= info
.height
;
887 bool Texture::GetLevelType(
888 GLint target
, GLint level
, GLenum
* type
, GLenum
* internal_format
) const {
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) {
897 *internal_format
= info
.internal_format
;
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
;
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
;
931 case GL_TEXTURE_MAG_FILTER
:
932 if (!feature_info
->validators()->texture_mag_filter_mode
.IsValid(param
)) {
933 return GL_INVALID_ENUM
;
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());
943 GetMemTracker()->TrackMemAlloc(estimated_size());
945 case GL_TEXTURE_WRAP_R
:
946 if (!feature_info
->validators()->texture_wrap_mode
.IsValid(param
)) {
947 return GL_INVALID_ENUM
;
951 case GL_TEXTURE_WRAP_S
:
952 if (!feature_info
->validators()->texture_wrap_mode
.IsValid(param
)) {
953 return GL_INVALID_ENUM
;
957 case GL_TEXTURE_WRAP_T
:
958 if (!feature_info
->validators()->texture_wrap_mode
.IsValid(param
)) {
959 return GL_INVALID_ENUM
;
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
;
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
;
975 case GL_TEXTURE_BASE_LEVEL
:
977 return GL_INVALID_VALUE
;
981 case GL_TEXTURE_MAX_LEVEL
:
983 return GL_INVALID_VALUE
;
987 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
989 return GL_INVALID_VALUE
;
992 case GL_TEXTURE_USAGE_ANGLE
:
993 if (!feature_info
->validators()->texture_usage
.IsValid(param
)) {
994 return GL_INVALID_ENUM
;
1000 return GL_INVALID_ENUM
;
1002 Update(feature_info
);
1004 UpdateCanRenderCondition();
1008 GLenum
Texture::SetParameterf(
1009 const FeatureInfo
* feature_info
, GLenum pname
, GLfloat param
) {
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
:
1029 case GL_TEXTURE_MAX_LOD
:
1032 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
1034 return GL_INVALID_VALUE
;
1039 return GL_INVALID_ENUM
;
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;
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
;
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
,
1086 level0
.internal_format
,
1092 texture_level0_complete_
= false;
1096 texture_level0_dirty_
= false;
1098 cube_complete_
&= texture_level0_complete_
;
1100 if (texture_complete_
&& texture_mips_dirty_
) {
1101 texture_mips_complete_
= true;
1103 ii
< face_infos_
.size() && texture_mips_complete_
;
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
,
1112 level_info
.internal_format
,
1118 texture_mips_complete_
= false;
1123 texture_mips_dirty_
= false;
1125 texture_complete_
&= texture_mips_complete_
;
1128 bool Texture::ClearRenderableLevels(GLES2Decoder
* decoder
) {
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
)) {
1145 UpdateSafeToRenderFrom(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())) {
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_
)
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
) {
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())) {
1178 Texture::LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
1180 DCHECK(target
== info
.target
);
1182 if (info
.target
== 0 ||
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
,
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
);
1216 UpdateCanRenderCondition();
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
) {
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();
1237 void Texture::OnWillModifyPixels() {
1238 gfx::GLImage
* image
= GetLevelImage(target(), 0);
1240 image
->WillModifyTexImage();
1243 void Texture::OnDidModifyPixels() {
1244 gfx::GLImage
* image
= GetLevelImage(target(), 0);
1246 image
->DidModifyTexImage();
1249 TextureRef::TextureRef(TextureManager
* manager
,
1252 : manager_(manager
),
1254 client_id_(client_id
),
1258 texture_
->AddTextureRef(this);
1259 manager_
->StartTracking(this);
1262 scoped_refptr
<TextureRef
> TextureRef::Create(TextureManager
* manager
,
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_
);
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
,
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),
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
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
]);
1339 scoped_refptr
<TextureRef
>
1340 TextureManager::CreateDefaultAndBlackTextures(
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.
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
) {
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
);
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
);
1375 for (int ii
= 0; ii
< GLES2Util::kNumFaces
; ++ii
) {
1376 SetLevelInfo(default_texture
.get(),
1377 GLES2Util::IndexToGLFaceTarget(ii
),
1389 if (needs_initialization
) {
1390 SetLevelInfo(default_texture
.get(),
1402 SetLevelInfo(default_texture
.get(),
1403 GL_TEXTURE_EXTERNAL_OES
,
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 &&
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
) {
1443 ->SetTarget(feature_info_
.get(), target
, MaxLevelsForTarget(target
));
1446 void TextureManager::SetLevelCleared(TextureRef
* ref
,
1451 ref
->texture()->SetLevelCleared(target
, level
, cleared
);
1454 bool TextureManager::ClearRenderableLevels(
1455 GLES2Decoder
* decoder
, TextureRef
* ref
) {
1457 return ref
->texture()->ClearRenderableLevels(decoder
);
1460 bool TextureManager::ClearTextureLevel(
1461 GLES2Decoder
* decoder
, TextureRef
* ref
,
1462 GLenum target
, GLint level
) {
1464 Texture
* texture
= ref
->texture();
1465 if (texture
->num_uncleared_mips() == 0) {
1468 bool result
= texture
->ClearLevel(decoder
, target
, level
);
1469 texture
->UpdateCleared();
1473 void TextureManager::SetLevelInfo(
1477 GLenum internal_format
,
1486 Texture
* texture
= ref
->texture();
1488 texture
->GetMemTracker()->TrackMemFree(texture
->estimated_size());
1489 texture
->SetLevelInfo(feature_info_
.get(),
1500 texture
->GetMemTracker()->TrackMemAlloc(texture
->estimated_size());
1503 Texture
* TextureManager::Produce(TextureRef
* ref
) {
1505 return ref
->texture();
1508 TextureRef
* TextureManager::Consume(
1512 scoped_refptr
<TextureRef
> ref(new TextureRef(this, client_id
, texture
));
1513 bool result
= textures_
.insert(std::make_pair(client_id
, ref
)).second
;
1518 void TextureManager::SetParameteri(
1519 const char* function_name
, ErrorState
* error_state
,
1520 TextureRef
* ref
, GLenum pname
, GLint param
) {
1521 DCHECK(error_state
);
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");
1530 ERRORSTATE_SET_GL_ERROR_INVALID_PARAMI(
1531 error_state
, result
, function_name
, pname
, param
);
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
);
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");
1554 ERRORSTATE_SET_GL_ERROR_INVALID_PARAMF(
1555 error_state
, result
, function_name
, pname
, param
);
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
) {
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());
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
);
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();
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())
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();
1623 if (texture
->HasImages()) {
1624 DCHECK_NE(0, 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();
1644 case GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
:
1645 return memory_tracker_unmanaged_
.get();
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
)
1665 GLsizei
TextureManager::ComputeMipMapCount(GLenum target
,
1670 case GL_TEXTURE_EXTERNAL_OES
:
1674 base::bits::Log2Floor(std::max(std::max(width
, height
), depth
));
1678 void TextureManager::SetLevelImage(
1682 gfx::GLImage
* image
) {
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(
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
,
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());
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");
1759 if (!validators
->pixel_type
.IsValid(type
)) {
1760 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1761 error_state
, function_name
, type
, "type");
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");
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");
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());
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
;
1799 texture
= unit
.bound_texture_2d
.get();
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();
1810 case GL_TEXTURE_EXTERNAL_OES
:
1811 texture
= unit
.bound_texture_external_oes
.get();
1813 case GL_TEXTURE_RECTANGLE_ARB
:
1814 texture
= unit
.bound_texture_rectangle_arb
.get();
1817 texture
= unit
.bound_texture_3d
.get();
1819 case GL_TEXTURE_2D_ARRAY
:
1820 texture
= unit
.bound_texture_2d_array
.get();
1829 TextureRef
* TextureManager::GetTextureInfoForTargetUnlessDefault(
1830 ContextState
* state
, GLenum target
) {
1831 TextureRef
* texture
= GetTextureInfoForTarget(state
, target
);
1834 if (texture
== GetDefaultTextureInfo(target
))
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");
1854 if (!ValidateTextureParameters(
1855 error_state
, function_name
, args
.format
, args
.type
,
1856 args
.internal_format
, args
.level
)) {
1859 if (!ValidForTarget(args
.target
, args
.level
,
1860 args
.width
, args
.height
, args
.depth
) ||
1862 ERRORSTATE_SET_GL_ERROR(
1863 error_state
, GL_INVALID_VALUE
, function_name
,
1864 "dimensions out of range");
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");
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");
1882 if (local_texture_ref
->texture()->IsImmutable()) {
1883 ERRORSTATE_SET_GL_ERROR(
1884 error_state
, GL_INVALID_OPERATION
, function_name
,
1885 "texture is immutable");
1889 if (!memory_tracker_managed_
->EnsureGPUMemoryAvailable(args
.pixels_size
)) {
1890 ERRORSTATE_SET_GL_ERROR(error_state
, GL_OUT_OF_MEMORY
, function_name
,
1895 // Write the TextureReference since this is valid.
1896 *texture_ref
= local_texture_ref
;
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
)) {
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
)
1921 if (format
== GL_SRGB_ALPHA_EXT
)
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.
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;
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
);
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;
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
);
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
) {
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