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 "base/thread_task_runner_handle.h"
15 #include "base/trace_event/memory_dump_manager.h"
16 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
17 #include "gpu/command_buffer/service/context_state.h"
18 #include "gpu/command_buffer/service/error_state.h"
19 #include "gpu/command_buffer/service/feature_info.h"
20 #include "gpu/command_buffer/service/framebuffer_manager.h"
21 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
22 #include "gpu/command_buffer/service/mailbox_manager.h"
23 #include "gpu/command_buffer/service/memory_tracking.h"
24 #include "ui/gl/gl_implementation.h"
25 #include "ui/gl/trace_util.h"
32 // This should contain everything to uniquely identify a Texture.
33 const char TextureTag
[] = "|Texture|";
34 struct TextureSignature
{
43 GLenum internal_format_
;
61 // Since we will be hashing this signature structure, the padding must be
62 // zero initialized. Although the C++11 specifications specify that this is
63 // true, we will use a constructor with a memset to further enforce it instead
64 // of relying on compilers adhering to this deep dark corner specification.
65 TextureSignature(GLenum target
,
73 GLenum internal_format
,
90 memset(this, 0, sizeof(TextureSignature
));
93 min_filter_
= min_filter
;
94 mag_filter_
= mag_filter
;
99 internal_format_
= internal_format
;
100 compare_func_
= compare_func
;
101 compare_mode_
= compare_mode
;
107 base_level_
= base_level
;
109 max_level_
= max_level
;
112 has_image_
= has_image
;
113 can_render_
= can_render
;
114 can_render_to_
= can_render_to
;
119 class FormatTypeValidator
{
121 FormatTypeValidator() {
122 static const FormatType kSupportedFormatTypes
[] = {
124 { GL_RGB
, GL_RGB
, GL_UNSIGNED_BYTE
},
125 { GL_RGB
, GL_RGB
, GL_UNSIGNED_SHORT_5_6_5
},
126 { GL_RGBA
, GL_RGBA
, GL_UNSIGNED_BYTE
},
127 { GL_RGBA
, GL_RGBA
, GL_UNSIGNED_SHORT_4_4_4_4
},
128 { GL_RGBA
, GL_RGBA
, GL_UNSIGNED_SHORT_5_5_5_1
},
129 { GL_LUMINANCE_ALPHA
, GL_LUMINANCE_ALPHA
, GL_UNSIGNED_BYTE
},
130 { GL_LUMINANCE
, GL_LUMINANCE
, GL_UNSIGNED_BYTE
},
131 { GL_ALPHA
, GL_ALPHA
, GL_UNSIGNED_BYTE
},
132 // Exposed by GL_OES_texture_float and GL_OES_texture_half_float
133 { GL_RGB
, GL_RGB
, GL_FLOAT
},
134 { GL_RGBA
, GL_RGBA
, GL_FLOAT
},
135 { GL_LUMINANCE_ALPHA
, GL_LUMINANCE_ALPHA
, GL_FLOAT
},
136 { GL_LUMINANCE
, GL_LUMINANCE
, GL_FLOAT
},
137 { GL_ALPHA
, GL_ALPHA
, GL_FLOAT
},
138 { GL_RGB
, GL_RGB
, GL_HALF_FLOAT_OES
},
139 { GL_RGBA
, GL_RGBA
, GL_HALF_FLOAT_OES
},
140 { GL_LUMINANCE_ALPHA
, GL_LUMINANCE_ALPHA
, GL_HALF_FLOAT_OES
},
141 { GL_LUMINANCE
, GL_LUMINANCE
, GL_HALF_FLOAT_OES
},
142 { GL_ALPHA
, GL_ALPHA
, GL_HALF_FLOAT_OES
},
143 // Exposed by GL_ANGLE_depth_texture
144 { GL_DEPTH_COMPONENT
, GL_DEPTH_COMPONENT
, GL_UNSIGNED_SHORT
},
145 { GL_DEPTH_COMPONENT
, GL_DEPTH_COMPONENT
, GL_UNSIGNED_INT
},
146 { GL_DEPTH_STENCIL
, GL_DEPTH_STENCIL
, GL_UNSIGNED_INT_24_8
},
147 // Exposed by GL_EXT_sRGB
148 { GL_SRGB
, GL_SRGB
, GL_UNSIGNED_BYTE
},
149 { GL_SRGB_ALPHA
, GL_SRGB_ALPHA
, GL_UNSIGNED_BYTE
},
150 // Exposed by GL_EXT_texture_format_BGRA8888
151 { GL_BGRA_EXT
, GL_BGRA_EXT
, GL_UNSIGNED_BYTE
},
152 // Exposed by GL_EXT_texture_rg
153 { GL_RED
, GL_RED
, GL_UNSIGNED_BYTE
},
154 { GL_RG
, GL_RG
, GL_UNSIGNED_BYTE
},
155 { GL_RED
, GL_RED
, GL_FLOAT
},
156 { GL_RG
, GL_RG
, GL_FLOAT
},
157 { GL_RED
, GL_RED
, GL_HALF_FLOAT_OES
},
158 { GL_RG
, GL_RG
, GL_HALF_FLOAT_OES
},
161 { GL_R8
, GL_RED
, GL_UNSIGNED_BYTE
},
162 { GL_R8_SNORM
, GL_RED
, GL_BYTE
},
163 { GL_R16F
, GL_RED
, GL_HALF_FLOAT
},
164 { GL_R16F
, GL_RED
, GL_FLOAT
},
165 { GL_R32F
, GL_RED
, GL_FLOAT
},
166 { GL_R8UI
, GL_RED_INTEGER
, GL_UNSIGNED_BYTE
},
167 { GL_R8I
, GL_RED_INTEGER
, GL_BYTE
},
168 { GL_R16UI
, GL_RED_INTEGER
, GL_UNSIGNED_SHORT
},
169 { GL_R16I
, GL_RED_INTEGER
, GL_SHORT
},
170 { GL_R32UI
, GL_RED_INTEGER
, GL_UNSIGNED_INT
},
171 { GL_R32I
, GL_RED_INTEGER
, GL_INT
},
172 { GL_RG8
, GL_RG
, GL_UNSIGNED_BYTE
},
173 { GL_RG8_SNORM
, GL_RG
, GL_BYTE
},
174 { GL_RG16F
, GL_RG
, GL_HALF_FLOAT
},
175 { GL_RG16F
, GL_RG
, GL_FLOAT
},
176 { GL_RG32F
, GL_RG
, GL_FLOAT
},
177 { GL_RG8UI
, GL_RG_INTEGER
, GL_UNSIGNED_BYTE
},
178 { GL_RG8I
, GL_RG_INTEGER
, GL_BYTE
},
179 { GL_RG16UI
, GL_RG_INTEGER
, GL_UNSIGNED_SHORT
},
180 { GL_RG16I
, GL_RG_INTEGER
, GL_SHORT
},
181 { GL_RG32UI
, GL_RG_INTEGER
, GL_UNSIGNED_INT
},
182 { GL_RG32I
, GL_RG_INTEGER
, GL_INT
},
183 { GL_RGB8
, GL_RGB
, GL_UNSIGNED_BYTE
},
184 { GL_SRGB8
, GL_RGB
, GL_UNSIGNED_BYTE
},
185 { GL_RGB565
, GL_RGB
, GL_UNSIGNED_BYTE
, },
186 { GL_RGB565
, GL_RGB
, GL_UNSIGNED_SHORT_5_6_5
},
187 { GL_RGB8_SNORM
, GL_RGB
, GL_BYTE
},
188 { GL_R11F_G11F_B10F
, GL_RGB
, GL_UNSIGNED_INT_10F_11F_11F_REV
},
189 { GL_R11F_G11F_B10F
, GL_RGB
, GL_HALF_FLOAT
},
190 { GL_R11F_G11F_B10F
, GL_RGB
, GL_FLOAT
},
191 { GL_RGB9_E5
, GL_RGB
, GL_UNSIGNED_INT_5_9_9_9_REV
},
192 { GL_RGB9_E5
, GL_RGB
, GL_HALF_FLOAT
},
193 { GL_RGB9_E5
, GL_RGB
, GL_FLOAT
},
194 { GL_RGB16F
, GL_RGB
, GL_HALF_FLOAT
},
195 { GL_RGB16F
, GL_RGB
, GL_FLOAT
},
196 { GL_RGB32F
, GL_RGB
, GL_FLOAT
},
197 { GL_RGB8UI
, GL_RGB_INTEGER
, GL_UNSIGNED_BYTE
},
198 { GL_RGB8I
, GL_RGB_INTEGER
, GL_BYTE
},
199 { GL_RGB16UI
, GL_RGB_INTEGER
, GL_UNSIGNED_SHORT
},
200 { GL_RGB16I
, GL_RGB_INTEGER
, GL_SHORT
},
201 { GL_RGB32UI
, GL_RGB_INTEGER
, GL_UNSIGNED_INT
},
202 { GL_RGB32I
, GL_RGB_INTEGER
, GL_INT
},
203 { GL_RGBA8
, GL_RGBA
, GL_UNSIGNED_BYTE
},
204 { GL_SRGB8_ALPHA8
, GL_RGBA
, GL_UNSIGNED_BYTE
},
205 { GL_RGBA8_SNORM
, GL_RGBA
, GL_BYTE
},
206 { GL_RGB5_A1
, GL_RGBA
, GL_UNSIGNED_BYTE
},
207 { GL_RGB5_A1
, GL_RGBA
, GL_UNSIGNED_SHORT_5_5_5_1
},
208 { GL_RGB5_A1
, GL_RGBA
, GL_UNSIGNED_INT_2_10_10_10_REV
},
209 { GL_RGBA4
, GL_RGBA
, GL_UNSIGNED_BYTE
},
210 { GL_RGBA4
, GL_RGBA
, GL_UNSIGNED_SHORT_4_4_4_4
},
211 { GL_RGB10_A2
, GL_RGBA
, GL_UNSIGNED_INT_2_10_10_10_REV
},
212 { GL_RGBA16F
, GL_RGBA
, GL_HALF_FLOAT
},
213 { GL_RGBA16F
, GL_RGBA
, GL_FLOAT
},
214 { GL_RGBA32F
, GL_RGBA
, GL_FLOAT
},
215 { GL_RGBA8UI
, GL_RGBA_INTEGER
, GL_UNSIGNED_BYTE
},
216 { GL_RGBA8I
, GL_RGBA_INTEGER
, GL_BYTE
},
217 { GL_RGB10_A2UI
, GL_RGBA_INTEGER
, GL_UNSIGNED_INT_2_10_10_10_REV
},
218 { GL_RGBA16UI
, GL_RGBA_INTEGER
, GL_UNSIGNED_SHORT
},
219 { GL_RGBA16I
, GL_RGBA_INTEGER
, GL_SHORT
},
220 { GL_RGBA32I
, GL_RGBA_INTEGER
, GL_INT
},
221 { GL_RGBA32UI
, GL_RGBA_INTEGER
, GL_UNSIGNED_INT
},
222 { GL_DEPTH_COMPONENT16
, GL_DEPTH_COMPONENT
, GL_UNSIGNED_SHORT
},
223 { GL_DEPTH_COMPONENT16
, GL_DEPTH_COMPONENT
, GL_UNSIGNED_INT
},
224 { GL_DEPTH_COMPONENT24
, GL_DEPTH_COMPONENT
, GL_UNSIGNED_INT
},
225 { GL_DEPTH_COMPONENT32F
, GL_DEPTH_COMPONENT
, GL_FLOAT
},
226 { GL_DEPTH24_STENCIL8
, GL_DEPTH_STENCIL
, GL_UNSIGNED_INT_24_8
},
227 { GL_DEPTH32F_STENCIL8
, GL_DEPTH_STENCIL
,
228 GL_FLOAT_32_UNSIGNED_INT_24_8_REV
},
231 for (size_t ii
= 0; ii
< arraysize(kSupportedFormatTypes
); ++ii
) {
232 supported_combinations_
.insert(kSupportedFormatTypes
[ii
]);
236 // This may be accessed from multiple threads.
237 bool IsValid(GLenum internal_format
, GLenum format
, GLenum type
) const {
238 FormatType query
= { internal_format
, format
, type
};
239 return supported_combinations_
.find(query
) != supported_combinations_
.end();
243 // TODO(zmo): once std::tuple is allowed, switch over to that.
245 GLenum internal_format
;
250 struct FormatTypeCompare
{
251 bool operator() (const FormatType
& lhs
, const FormatType
& rhs
) const {
252 return (lhs
.internal_format
< rhs
.internal_format
||
253 ((lhs
.internal_format
== rhs
.internal_format
) &&
254 (lhs
.format
< rhs
.format
)) ||
255 ((lhs
.internal_format
== rhs
.internal_format
) &&
256 (lhs
.format
== rhs
.format
) &&
257 (lhs
.type
< rhs
.type
)));
261 // This class needs to be thread safe, so once supported_combinations_
262 // are initialized in the constructor, it should never be modified later.
263 std::set
<FormatType
, FormatTypeCompare
> supported_combinations_
;
266 base::LazyInstance
<const FormatTypeValidator
>::Leaky g_format_type_validator
=
267 LAZY_INSTANCE_INITIALIZER
;
269 } // namespace anonymous
271 TextureManager::DestructionObserver::DestructionObserver() {}
273 TextureManager::DestructionObserver::~DestructionObserver() {}
275 TextureManager::~TextureManager() {
276 for (unsigned int i
= 0; i
< destruction_observers_
.size(); i
++)
277 destruction_observers_
[i
]->OnTextureManagerDestroying(this);
279 DCHECK(textures_
.empty());
281 // If this triggers, that means something is keeping a reference to
282 // a Texture belonging to this.
283 CHECK_EQ(texture_count_
, 0u);
285 DCHECK_EQ(0, num_unrenderable_textures_
);
286 DCHECK_EQ(0, num_unsafe_textures_
);
287 DCHECK_EQ(0, num_uncleared_mips_
);
288 DCHECK_EQ(0, num_images_
);
290 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
294 void TextureManager::Destroy(bool have_context
) {
295 have_context_
= have_context
;
297 for (int ii
= 0; ii
< kNumDefaultTextures
; ++ii
) {
298 default_textures_
[ii
] = NULL
;
302 glDeleteTextures(arraysize(black_texture_ids_
), black_texture_ids_
);
305 DCHECK_EQ(0u, memory_tracker_managed_
->GetMemRepresented());
306 DCHECK_EQ(0u, memory_tracker_unmanaged_
->GetMemRepresented());
309 Texture::Texture(GLuint service_id
)
310 : mailbox_manager_(NULL
),
311 memory_tracking_ref_(NULL
),
312 service_id_(service_id
),
314 num_uncleared_mips_(0),
317 min_filter_(GL_NEAREST_MIPMAP_LINEAR
),
318 mag_filter_(GL_LINEAR
),
323 pool_(GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
),
324 compare_func_(GL_LEQUAL
),
325 compare_mode_(GL_NONE
),
331 texture_complete_(false),
332 texture_mips_dirty_(false),
333 texture_mips_complete_(false),
334 cube_complete_(false),
335 texture_level0_dirty_(false),
336 texture_level0_complete_(false),
338 has_been_bound_(false),
339 framebuffer_attachment_count_(0),
343 can_render_condition_(CAN_RENDER_ALWAYS
),
344 texture_max_anisotropy_initialized_(false) {
347 Texture::~Texture() {
348 if (mailbox_manager_
)
349 mailbox_manager_
->TextureDeleted(this);
352 void Texture::AddTextureRef(TextureRef
* ref
) {
353 DCHECK(refs_
.find(ref
) == refs_
.end());
355 if (!memory_tracking_ref_
) {
356 memory_tracking_ref_
= ref
;
357 GetMemTracker()->TrackMemAlloc(estimated_size());
361 void Texture::RemoveTextureRef(TextureRef
* ref
, bool have_context
) {
362 if (memory_tracking_ref_
== ref
) {
363 GetMemTracker()->TrackMemFree(estimated_size());
364 memory_tracking_ref_
= NULL
;
366 size_t result
= refs_
.erase(ref
);
367 DCHECK_EQ(result
, 1u);
370 GLuint id
= service_id();
371 glDeleteTextures(1, &id
);
374 } else if (memory_tracking_ref_
== NULL
) {
375 // TODO(piman): tune ownership semantics for cross-context group shared
377 memory_tracking_ref_
= *refs_
.begin();
378 GetMemTracker()->TrackMemAlloc(estimated_size());
382 MemoryTypeTracker
* Texture::GetMemTracker() {
383 DCHECK(memory_tracking_ref_
);
384 return memory_tracking_ref_
->manager()->GetMemTracker(pool_
);
387 Texture::LevelInfo::LevelInfo()
400 Texture::LevelInfo::LevelInfo(const LevelInfo
& rhs
)
401 : cleared_rect(rhs
.cleared_rect
),
404 internal_format(rhs
.internal_format
),
412 estimated_size(rhs
.estimated_size
) {
415 Texture::LevelInfo::~LevelInfo() {
418 Texture::FaceInfo::FaceInfo()
419 : num_mip_levels(0) {
422 Texture::FaceInfo::~FaceInfo() {
425 Texture::CanRenderCondition
Texture::GetCanRenderCondition() const {
427 return CAN_RENDER_ALWAYS
;
429 if (target_
!= GL_TEXTURE_EXTERNAL_OES
) {
430 if (face_infos_
.empty()) {
431 return CAN_RENDER_NEVER
;
434 const Texture::LevelInfo
& first_face
= face_infos_
[0].level_infos
[0];
435 if (first_face
.width
== 0 ||
436 first_face
.height
== 0 ||
437 first_face
.depth
== 0) {
438 return CAN_RENDER_NEVER
;
442 bool needs_mips
= NeedsMips();
444 if (!texture_complete())
445 return CAN_RENDER_NEVER
;
448 if (target_
== GL_TEXTURE_CUBE_MAP
&& !cube_complete())
449 return CAN_RENDER_NEVER
;
451 bool is_npot_compatible
= !needs_mips
&&
452 wrap_s_
== GL_CLAMP_TO_EDGE
&&
453 wrap_t_
== GL_CLAMP_TO_EDGE
;
455 if (!is_npot_compatible
) {
456 if (target_
== GL_TEXTURE_RECTANGLE_ARB
)
457 return CAN_RENDER_NEVER
;
459 return CAN_RENDER_ONLY_IF_NPOT
;
462 return CAN_RENDER_ALWAYS
;
465 bool Texture::CanRender(const FeatureInfo
* feature_info
) const {
466 switch (can_render_condition_
) {
467 case CAN_RENDER_ALWAYS
:
469 case CAN_RENDER_NEVER
:
471 case CAN_RENDER_ONLY_IF_NPOT
:
474 return feature_info
->feature_flags().npot_ok
;
477 void Texture::AddToSignature(
478 const FeatureInfo
* feature_info
,
481 std::string
* signature
) const {
482 DCHECK(feature_info
);
485 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
486 DCHECK_LT(static_cast<size_t>(face_index
),
488 DCHECK_LT(static_cast<size_t>(level
),
489 face_infos_
[face_index
].level_infos
.size());
491 const Texture::LevelInfo
& info
=
492 face_infos_
[face_index
].level_infos
[level
];
494 TextureSignature
signature_data(target
,
502 info
.internal_format
,
515 info
.image
.get() != NULL
,
516 CanRender(feature_info
),
520 signature
->append(TextureTag
, sizeof(TextureTag
));
521 signature
->append(reinterpret_cast<const char*>(&signature_data
),
522 sizeof(signature_data
));
525 void Texture::SetMailboxManager(MailboxManager
* mailbox_manager
) {
526 DCHECK(!mailbox_manager_
|| mailbox_manager_
== mailbox_manager
);
527 mailbox_manager_
= mailbox_manager
;
530 bool Texture::MarkMipmapsGenerated(
531 const FeatureInfo
* feature_info
) {
532 if (!CanGenerateMipmaps(feature_info
)) {
535 for (size_t ii
= 0; ii
< face_infos_
.size(); ++ii
) {
536 const Texture::FaceInfo
& face_info
= face_infos_
[ii
];
537 const Texture::LevelInfo
& level0_info
= face_info
.level_infos
[0];
538 GLsizei width
= level0_info
.width
;
539 GLsizei height
= level0_info
.height
;
540 GLsizei depth
= level0_info
.depth
;
541 GLenum target
= target_
== GL_TEXTURE_2D
? GL_TEXTURE_2D
:
542 GLES2Util::IndexToGLFaceTarget(ii
);
544 const GLsizei num_mips
= face_info
.num_mip_levels
;
545 for (GLsizei level
= 1; level
< num_mips
; ++level
) {
546 width
= std::max(1, width
>> 1);
547 height
= std::max(1, height
>> 1);
548 depth
= std::max(1, depth
>> 1);
549 SetLevelInfo(feature_info
, target
, level
, level0_info
.internal_format
,
550 width
, height
, depth
, level0_info
.border
, level0_info
.format
,
551 level0_info
.type
, gfx::Rect(width
, height
));
558 void Texture::SetTarget(
559 const FeatureInfo
* feature_info
, GLenum target
, GLint max_levels
) {
560 DCHECK_EQ(0u, target_
); // you can only set this once.
562 size_t num_faces
= (target
== GL_TEXTURE_CUBE_MAP
) ? 6 : 1;
563 face_infos_
.resize(num_faces
);
564 for (size_t ii
= 0; ii
< num_faces
; ++ii
) {
565 face_infos_
[ii
].level_infos
.resize(max_levels
);
568 if (target
== GL_TEXTURE_EXTERNAL_OES
|| target
== GL_TEXTURE_RECTANGLE_ARB
) {
569 min_filter_
= GL_LINEAR
;
570 wrap_s_
= wrap_t_
= GL_CLAMP_TO_EDGE
;
573 if (target
== GL_TEXTURE_EXTERNAL_OES
) {
576 Update(feature_info
);
577 UpdateCanRenderCondition();
580 bool Texture::CanGenerateMipmaps(
581 const FeatureInfo
* feature_info
) const {
582 if ((npot() && !feature_info
->feature_flags().npot_ok
) ||
583 face_infos_
.empty() ||
584 target_
== GL_TEXTURE_EXTERNAL_OES
||
585 target_
== GL_TEXTURE_RECTANGLE_ARB
) {
589 // Can't generate mips for depth or stencil textures.
590 const Texture::LevelInfo
& first
= face_infos_
[0].level_infos
[0];
591 uint32 channels
= GLES2Util::GetChannelsForFormat(first
.format
);
592 if (channels
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) {
596 // TODO(gman): Check internal_format, format and type.
597 for (size_t ii
= 0; ii
< face_infos_
.size(); ++ii
) {
598 const LevelInfo
& info
= face_infos_
[ii
].level_infos
[0];
599 if ((info
.target
== 0) || (info
.width
!= first
.width
) ||
600 (info
.height
!= first
.height
) || (info
.depth
!= 1) ||
601 (info
.format
!= first
.format
) ||
602 (info
.internal_format
!= first
.internal_format
) ||
603 (info
.type
!= first
.type
) ||
604 feature_info
->validators()->compressed_texture_format
.IsValid(
605 info
.internal_format
) ||
613 bool Texture::TextureIsNPOT(GLsizei width
,
616 return (GLES2Util::IsNPOT(width
) ||
617 GLES2Util::IsNPOT(height
) ||
618 GLES2Util::IsNPOT(depth
));
621 bool Texture::TextureFaceComplete(const Texture::LevelInfo
& first_face
,
624 GLenum internal_format
,
630 bool complete
= (target
!= 0 && depth
== 1);
631 if (face_index
!= 0) {
632 complete
&= (width
== first_face
.width
&&
633 height
== first_face
.height
&&
634 internal_format
== first_face
.internal_format
&&
635 format
== first_face
.format
&&
636 type
== first_face
.type
);
641 bool Texture::TextureMipComplete(const Texture::LevelInfo
& level0_face
,
644 GLenum internal_format
,
650 bool complete
= (target
!= 0);
652 const GLsizei mip_width
= std::max(1, level0_face
.width
>> level
);
653 const GLsizei mip_height
= std::max(1, level0_face
.height
>> level
);
654 const GLsizei mip_depth
= std::max(1, level0_face
.depth
>> level
);
656 complete
&= (width
== mip_width
&&
657 height
== mip_height
&&
658 depth
== mip_depth
&&
659 internal_format
== level0_face
.internal_format
&&
660 format
== level0_face
.format
&&
661 type
== level0_face
.type
);
666 void Texture::SetLevelClearedRect(GLenum target
,
668 const gfx::Rect
& cleared_rect
) {
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
, info
.width
, info
.height
, cleared_rect
);
681 void Texture::SetLevelCleared(GLenum target
, GLint level
, bool cleared
) {
683 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
684 DCHECK_LT(static_cast<size_t>(face_index
), face_infos_
.size());
685 DCHECK_LT(static_cast<size_t>(level
),
686 face_infos_
[face_index
].level_infos
.size());
687 Texture::LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
688 UpdateMipCleared(&info
, info
.width
, info
.height
,
689 cleared
? gfx::Rect(info
.width
, info
.height
) : gfx::Rect());
693 void Texture::UpdateCleared() {
694 if (face_infos_
.empty()) {
698 const bool cleared
= (num_uncleared_mips_
== 0);
700 // If texture is uncleared and is attached to a framebuffer,
701 // that framebuffer must be marked possibly incomplete.
702 if (!cleared
&& IsAttachedToFramebuffer()) {
703 IncAllFramebufferStateChangeCount();
706 UpdateSafeToRenderFrom(cleared
);
709 void Texture::UpdateSafeToRenderFrom(bool cleared
) {
710 if (cleared_
== cleared
)
713 int delta
= cleared
? -1 : +1;
714 for (RefSet::iterator it
= refs_
.begin(); it
!= refs_
.end(); ++it
)
715 (*it
)->manager()->UpdateSafeToRenderFrom(delta
);
718 void Texture::UpdateMipCleared(LevelInfo
* info
,
721 const gfx::Rect
& cleared_rect
) {
722 bool was_cleared
= info
->cleared_rect
== gfx::Rect(info
->width
, info
->height
);
724 info
->height
= height
;
725 info
->cleared_rect
= cleared_rect
;
726 bool cleared
= info
->cleared_rect
== gfx::Rect(info
->width
, info
->height
);
727 if (cleared
== was_cleared
)
729 int delta
= cleared
? -1 : +1;
730 num_uncleared_mips_
+= delta
;
731 for (RefSet::iterator it
= refs_
.begin(); it
!= refs_
.end(); ++it
)
732 (*it
)->manager()->UpdateUnclearedMips(delta
);
735 void Texture::UpdateCanRenderCondition() {
736 CanRenderCondition can_render_condition
= GetCanRenderCondition();
737 if (can_render_condition_
== can_render_condition
)
739 for (RefSet::iterator it
= refs_
.begin(); it
!= refs_
.end(); ++it
)
740 (*it
)->manager()->UpdateCanRenderCondition(can_render_condition_
,
741 can_render_condition
);
742 can_render_condition_
= can_render_condition
;
745 void Texture::UpdateHasImages() {
746 if (face_infos_
.empty())
749 bool has_images
= false;
750 for (size_t ii
= 0; ii
< face_infos_
.size(); ++ii
) {
751 for (size_t jj
= 0; jj
< face_infos_
[ii
].level_infos
.size(); ++jj
) {
752 const Texture::LevelInfo
& info
= face_infos_
[ii
].level_infos
[jj
];
753 if (info
.image
.get() != NULL
) {
760 if (has_images_
== has_images
)
762 has_images_
= has_images
;
763 int delta
= has_images
? +1 : -1;
764 for (RefSet::iterator it
= refs_
.begin(); it
!= refs_
.end(); ++it
)
765 (*it
)->manager()->UpdateNumImages(delta
);
768 void Texture::IncAllFramebufferStateChangeCount() {
769 for (RefSet::iterator it
= refs_
.begin(); it
!= refs_
.end(); ++it
)
770 (*it
)->manager()->IncFramebufferStateChangeCount();
773 void Texture::SetLevelInfo(const FeatureInfo
* feature_info
,
776 GLenum internal_format
,
783 const gfx::Rect
& cleared_rect
) {
785 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
786 DCHECK_LT(static_cast<size_t>(face_index
),
788 DCHECK_LT(static_cast<size_t>(level
),
789 face_infos_
[face_index
].level_infos
.size());
791 DCHECK_GE(height
, 0);
793 Texture::LevelInfo
& info
=
794 face_infos_
[face_index
].level_infos
[level
];
796 // Update counters only if any attributes have changed. Counters are
797 // comparisons between the old and new values so it must be done before any
798 // assignment has been done to the LevelInfo.
799 if (info
.target
!= target
||
800 info
.internal_format
!= internal_format
||
801 info
.width
!= width
||
802 info
.height
!= height
||
803 info
.depth
!= depth
||
804 info
.format
!= format
||
807 // Calculate the mip level count.
808 face_infos_
[face_index
].num_mip_levels
=
809 TextureManager::ComputeMipMapCount(target_
, width
, height
, depth
);
811 // Update NPOT face count for the first level.
812 bool prev_npot
= TextureIsNPOT(info
.width
, info
.height
, info
.depth
);
813 bool now_npot
= TextureIsNPOT(width
, height
, depth
);
814 if (prev_npot
!= now_npot
)
815 num_npot_faces_
+= now_npot
? 1 : -1;
817 // Signify that level 0 has been changed, so they need to be reverified.
818 texture_level0_dirty_
= true;
821 // Signify that at least one of the mips has changed.
822 texture_mips_dirty_
= true;
825 info
.target
= target
;
827 info
.internal_format
= internal_format
;
829 info
.border
= border
;
830 info
.format
= format
;
834 UpdateMipCleared(&info
, width
, height
, cleared_rect
);
836 estimated_size_
-= info
.estimated_size
;
837 GLES2Util::ComputeImageDataSizes(
838 width
, height
, 1, format
, type
, 4, &info
.estimated_size
, NULL
, NULL
);
839 estimated_size_
+= info
.estimated_size
;
841 max_level_set_
= std::max(max_level_set_
, level
);
842 Update(feature_info
);
844 UpdateCanRenderCondition();
846 if (IsAttachedToFramebuffer()) {
847 // TODO(gman): If textures tracked which framebuffers they were attached to
848 // we could just mark those framebuffers as not complete.
849 IncAllFramebufferStateChangeCount();
853 bool Texture::ValidForTexture(
863 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
864 if (level
>= 0 && face_index
< face_infos_
.size() &&
865 static_cast<size_t>(level
) < face_infos_
[face_index
].level_infos
.size()) {
866 const LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
870 return SafeAddInt32(xoffset
, width
, &max_x
) &&
871 SafeAddInt32(yoffset
, height
, &max_y
) &&
872 SafeAddInt32(zoffset
, depth
, &max_z
) &&
876 max_x
<= info
.width
&&
877 max_y
<= info
.height
&&
878 max_z
<= info
.depth
&&
884 bool Texture::GetLevelSize(
885 GLint target
, GLint level
,
886 GLsizei
* width
, GLsizei
* height
, GLsizei
* depth
) const {
889 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
890 if (level
>= 0 && face_index
< face_infos_
.size() &&
891 static_cast<size_t>(level
) < face_infos_
[face_index
].level_infos
.size()) {
892 const LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
893 if (info
.target
!= 0) {
895 *height
= info
.height
;
904 bool Texture::GetLevelType(
905 GLint target
, GLint level
, GLenum
* type
, GLenum
* internal_format
) const {
907 DCHECK(internal_format
);
908 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
909 if (level
>= 0 && face_index
< face_infos_
.size() &&
910 static_cast<size_t>(level
) < face_infos_
[face_index
].level_infos
.size()) {
911 const LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
912 if (info
.target
!= 0) {
914 *internal_format
= info
.internal_format
;
921 GLenum
Texture::SetParameteri(
922 const FeatureInfo
* feature_info
, GLenum pname
, GLint param
) {
923 DCHECK(feature_info
);
925 if (target_
== GL_TEXTURE_EXTERNAL_OES
||
926 target_
== GL_TEXTURE_RECTANGLE_ARB
) {
927 if (pname
== GL_TEXTURE_MIN_FILTER
&&
928 (param
!= GL_NEAREST
&& param
!= GL_LINEAR
))
929 return GL_INVALID_ENUM
;
930 if ((pname
== GL_TEXTURE_WRAP_S
|| pname
== GL_TEXTURE_WRAP_T
) &&
931 param
!= GL_CLAMP_TO_EDGE
)
932 return GL_INVALID_ENUM
;
936 case GL_TEXTURE_MIN_LOD
:
937 case GL_TEXTURE_MAX_LOD
:
939 GLfloat fparam
= static_cast<GLfloat
>(param
);
940 return SetParameterf(feature_info
, pname
, fparam
);
942 case GL_TEXTURE_MIN_FILTER
:
943 if (!feature_info
->validators()->texture_min_filter_mode
.IsValid(param
)) {
944 return GL_INVALID_ENUM
;
948 case GL_TEXTURE_MAG_FILTER
:
949 if (!feature_info
->validators()->texture_mag_filter_mode
.IsValid(param
)) {
950 return GL_INVALID_ENUM
;
954 case GL_TEXTURE_POOL_CHROMIUM
:
955 if (!feature_info
->validators()->texture_pool
.IsValid(param
)) {
956 return GL_INVALID_ENUM
;
958 GetMemTracker()->TrackMemFree(estimated_size());
960 GetMemTracker()->TrackMemAlloc(estimated_size());
962 case GL_TEXTURE_WRAP_R
:
963 if (!feature_info
->validators()->texture_wrap_mode
.IsValid(param
)) {
964 return GL_INVALID_ENUM
;
968 case GL_TEXTURE_WRAP_S
:
969 if (!feature_info
->validators()->texture_wrap_mode
.IsValid(param
)) {
970 return GL_INVALID_ENUM
;
974 case GL_TEXTURE_WRAP_T
:
975 if (!feature_info
->validators()->texture_wrap_mode
.IsValid(param
)) {
976 return GL_INVALID_ENUM
;
980 case GL_TEXTURE_COMPARE_FUNC
:
981 if (!feature_info
->validators()->texture_compare_func
.IsValid(param
)) {
982 return GL_INVALID_ENUM
;
984 compare_func_
= param
;
986 case GL_TEXTURE_COMPARE_MODE
:
987 if (!feature_info
->validators()->texture_compare_mode
.IsValid(param
)) {
988 return GL_INVALID_ENUM
;
990 compare_mode_
= param
;
992 case GL_TEXTURE_BASE_LEVEL
:
994 return GL_INVALID_VALUE
;
998 case GL_TEXTURE_MAX_LEVEL
:
1000 return GL_INVALID_VALUE
;
1004 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
1006 return GL_INVALID_VALUE
;
1009 case GL_TEXTURE_USAGE_ANGLE
:
1010 if (!feature_info
->validators()->texture_usage
.IsValid(param
)) {
1011 return GL_INVALID_ENUM
;
1017 return GL_INVALID_ENUM
;
1019 Update(feature_info
);
1021 UpdateCanRenderCondition();
1025 GLenum
Texture::SetParameterf(
1026 const FeatureInfo
* feature_info
, GLenum pname
, GLfloat param
) {
1028 case GL_TEXTURE_MIN_FILTER
:
1029 case GL_TEXTURE_MAG_FILTER
:
1030 case GL_TEXTURE_POOL_CHROMIUM
:
1031 case GL_TEXTURE_WRAP_R
:
1032 case GL_TEXTURE_WRAP_S
:
1033 case GL_TEXTURE_WRAP_T
:
1034 case GL_TEXTURE_COMPARE_FUNC
:
1035 case GL_TEXTURE_COMPARE_MODE
:
1036 case GL_TEXTURE_BASE_LEVEL
:
1037 case GL_TEXTURE_MAX_LEVEL
:
1038 case GL_TEXTURE_USAGE_ANGLE
:
1040 GLint iparam
= static_cast<GLint
>(param
);
1041 return SetParameteri(feature_info
, pname
, iparam
);
1043 case GL_TEXTURE_MIN_LOD
:
1046 case GL_TEXTURE_MAX_LOD
:
1049 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
1051 return GL_INVALID_VALUE
;
1056 return GL_INVALID_ENUM
;
1061 void Texture::Update(const FeatureInfo
* feature_info
) {
1062 // Update npot status.
1063 // Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others
1064 npot_
= (target_
== GL_TEXTURE_EXTERNAL_OES
) || (num_npot_faces_
> 0);
1066 if (face_infos_
.empty()) {
1067 texture_complete_
= false;
1068 cube_complete_
= false;
1072 // Update texture_complete and cube_complete status.
1073 const Texture::FaceInfo
& first_face
= face_infos_
[0];
1074 const Texture::LevelInfo
& first_level
= first_face
.level_infos
[0];
1075 const GLsizei levels_needed
= first_face
.num_mip_levels
;
1078 max_level_set_
>= (levels_needed
- 1) && max_level_set_
>= 0;
1079 cube_complete_
= (face_infos_
.size() == 6) &&
1080 (first_level
.width
== first_level
.height
);
1082 if (first_level
.width
== 0 || first_level
.height
== 0) {
1083 texture_complete_
= false;
1084 } else if (first_level
.type
== GL_FLOAT
&&
1085 !feature_info
->feature_flags().enable_texture_float_linear
&&
1086 (min_filter_
!= GL_NEAREST_MIPMAP_NEAREST
||
1087 mag_filter_
!= GL_NEAREST
)) {
1088 texture_complete_
= false;
1089 } else if (first_level
.type
== GL_HALF_FLOAT_OES
&&
1090 !feature_info
->feature_flags().enable_texture_half_float_linear
&&
1091 (min_filter_
!= GL_NEAREST_MIPMAP_NEAREST
||
1092 mag_filter_
!= GL_NEAREST
)) {
1093 texture_complete_
= false;
1096 if (cube_complete_
&& texture_level0_dirty_
) {
1097 texture_level0_complete_
= true;
1098 for (size_t ii
= 0; ii
< face_infos_
.size(); ++ii
) {
1099 const Texture::LevelInfo
& level0
= face_infos_
[ii
].level_infos
[0];
1100 if (!TextureFaceComplete(first_level
,
1103 level0
.internal_format
,
1109 texture_level0_complete_
= false;
1113 texture_level0_dirty_
= false;
1115 cube_complete_
&= texture_level0_complete_
;
1117 if (texture_complete_
&& texture_mips_dirty_
) {
1118 texture_mips_complete_
= true;
1120 ii
< face_infos_
.size() && texture_mips_complete_
;
1122 const Texture::FaceInfo
& face_info
= face_infos_
[ii
];
1123 const Texture::LevelInfo
& level0
= face_info
.level_infos
[0];
1124 for (GLsizei jj
= 1; jj
< levels_needed
; ++jj
) {
1125 const Texture::LevelInfo
& level_info
= face_infos_
[ii
].level_infos
[jj
];
1126 if (!TextureMipComplete(level0
,
1129 level_info
.internal_format
,
1135 texture_mips_complete_
= false;
1140 texture_mips_dirty_
= false;
1142 texture_complete_
&= texture_mips_complete_
;
1145 bool Texture::ClearRenderableLevels(GLES2Decoder
* decoder
) {
1151 for (size_t ii
= 0; ii
< face_infos_
.size(); ++ii
) {
1152 const Texture::FaceInfo
& face_info
= face_infos_
[ii
];
1153 for (GLint jj
= 0; jj
< face_info
.num_mip_levels
; ++jj
) {
1154 const Texture::LevelInfo
& info
= face_info
.level_infos
[jj
];
1155 if (info
.target
!= 0) {
1156 if (!ClearLevel(decoder
, info
.target
, jj
)) {
1162 UpdateSafeToRenderFrom(true);
1166 gfx::Rect
Texture::GetLevelClearedRect(GLenum target
, GLint level
) const {
1167 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
1168 if (face_index
>= face_infos_
.size() ||
1169 level
>= static_cast<GLint
>(face_infos_
[face_index
].level_infos
.size())) {
1173 const Texture::LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
1175 return info
.cleared_rect
;
1178 bool Texture::IsLevelCleared(GLenum target
, GLint level
) const {
1179 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
1180 if (face_index
>= face_infos_
.size() ||
1181 level
>= static_cast<GLint
>(face_infos_
[face_index
].level_infos
.size())) {
1185 const Texture::LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
1187 return info
.cleared_rect
== gfx::Rect(info
.width
, info
.height
);
1190 void Texture::InitTextureMaxAnisotropyIfNeeded(GLenum target
) {
1191 if (texture_max_anisotropy_initialized_
)
1193 texture_max_anisotropy_initialized_
= true;
1194 GLfloat params
[] = { 1.0f
};
1195 glTexParameterfv(target
, GL_TEXTURE_MAX_ANISOTROPY_EXT
, params
);
1198 bool Texture::ClearLevel(
1199 GLES2Decoder
* decoder
, GLenum target
, GLint level
) {
1201 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
1202 if (face_index
>= face_infos_
.size() ||
1203 level
>= static_cast<GLint
>(face_infos_
[face_index
].level_infos
.size())) {
1207 Texture::LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
1209 DCHECK(target
== info
.target
);
1211 if (info
.target
== 0 ||
1212 info
.cleared_rect
== gfx::Rect(info
.width
, info
.height
) ||
1213 info
.width
== 0 || info
.height
== 0 || info
.depth
== 0) {
1217 // Clear all remaining sub regions.
1219 0, info
.cleared_rect
.x(), info
.cleared_rect
.right(), info
.width
};
1221 0, info
.cleared_rect
.y(), info
.cleared_rect
.bottom(), info
.height
};
1223 for (size_t j
= 0; j
< 3; ++j
) {
1224 for (size_t i
= 0; i
< 3; ++i
) {
1225 // Center of nine patch is already cleared.
1226 if (j
== 1 && i
== 1)
1229 gfx::Rect
rect(x
[i
], y
[j
], x
[i
+ 1] - x
[i
], y
[j
+ 1] - y
[j
]);
1233 // NOTE: It seems kind of gross to call back into the decoder for this
1234 // but only the decoder knows all the state (like unpack_alignment_)
1235 // that's needed to be able to call GL correctly.
1236 bool cleared
= decoder
->ClearLevel(this, info
.target
, info
.level
,
1237 info
.format
, info
.type
, rect
.x(),
1238 rect
.y(), rect
.width(), rect
.height());
1244 UpdateMipCleared(&info
, info
.width
, info
.height
,
1245 gfx::Rect(info
.width
, info
.height
));
1249 void Texture::SetLevelImage(
1250 const FeatureInfo
* feature_info
,
1253 gfx::GLImage
* image
) {
1254 DCHECK_GE(level
, 0);
1255 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
1256 DCHECK_LT(static_cast<size_t>(face_index
),
1257 face_infos_
.size());
1258 DCHECK_LT(static_cast<size_t>(level
),
1259 face_infos_
[face_index
].level_infos
.size());
1260 Texture::LevelInfo
& info
=
1261 face_infos_
[face_index
].level_infos
[level
];
1262 DCHECK_EQ(info
.target
, target
);
1263 DCHECK_EQ(info
.level
, level
);
1265 UpdateCanRenderCondition();
1269 gfx::GLImage
* Texture::GetLevelImage(GLint target
, GLint level
) const {
1270 if (target
!= GL_TEXTURE_2D
&& target
!= GL_TEXTURE_EXTERNAL_OES
&&
1271 target
!= GL_TEXTURE_RECTANGLE_ARB
) {
1275 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
1276 if (level
>= 0 && face_index
< face_infos_
.size() &&
1277 static_cast<size_t>(level
) < face_infos_
[face_index
].level_infos
.size()) {
1278 const LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
1279 if (info
.target
!= 0) {
1280 return info
.image
.get();
1286 void Texture::OnWillModifyPixels() {
1287 gfx::GLImage
* image
= GetLevelImage(target(), 0);
1289 image
->WillModifyTexImage();
1292 void Texture::OnDidModifyPixels() {
1293 gfx::GLImage
* image
= GetLevelImage(target(), 0);
1295 image
->DidModifyTexImage();
1298 void Texture::DumpLevelMemory(base::trace_event::ProcessMemoryDump
* pmd
,
1299 uint64_t client_tracing_id
,
1300 const std::string
& dump_name
) const {
1301 for (uint32_t face_index
= 0; face_index
< face_infos_
.size(); ++face_index
) {
1302 const auto& level_infos
= face_infos_
[face_index
].level_infos
;
1303 for (uint32_t level_index
= 0; level_index
< level_infos
.size();
1305 // Skip levels with no size. Textures will have empty levels for all
1306 // potential mip levels which are not in use.
1307 if (!level_infos
[level_index
].estimated_size
)
1310 if (level_infos
[level_index
].image
) {
1311 // If a level is backed by a GLImage, ask the GLImage to dump itself.
1312 level_infos
[level_index
].image
->OnMemoryDump(
1313 pmd
, client_tracing_id
,
1314 base::StringPrintf("%s/face_%d/level_%d", dump_name
.c_str(),
1315 face_index
, level_index
));
1317 // If a level is not backed by a GLImage, create a simple dump.
1318 base::trace_event::MemoryAllocatorDump
* dump
= pmd
->CreateAllocatorDump(
1319 base::StringPrintf("%s/face_%d/level_%d", dump_name
.c_str(),
1320 face_index
, level_index
));
1322 base::trace_event::MemoryAllocatorDump::kNameSize
,
1323 base::trace_event::MemoryAllocatorDump::kUnitsBytes
,
1324 static_cast<uint64_t>(level_infos
[level_index
].estimated_size
));
1330 TextureRef::TextureRef(TextureManager
* manager
,
1333 : manager_(manager
),
1335 client_id_(client_id
),
1339 texture_
->AddTextureRef(this);
1340 manager_
->StartTracking(this);
1343 scoped_refptr
<TextureRef
> TextureRef::Create(TextureManager
* manager
,
1345 GLuint service_id
) {
1346 return new TextureRef(manager
, client_id
, new Texture(service_id
));
1349 TextureRef::~TextureRef() {
1350 manager_
->StopTracking(this);
1351 texture_
->RemoveTextureRef(this, manager_
->have_context_
);
1355 TextureManager::TextureManager(MemoryTracker
* memory_tracker
,
1356 FeatureInfo
* feature_info
,
1357 GLint max_texture_size
,
1358 GLint max_cube_map_texture_size
,
1359 GLint max_rectangle_texture_size
,
1360 GLint max_3d_texture_size
,
1361 bool use_default_textures
)
1362 : memory_tracker_managed_(
1363 new MemoryTypeTracker(memory_tracker
, MemoryTracker::kManaged
)),
1364 memory_tracker_unmanaged_(
1365 new MemoryTypeTracker(memory_tracker
, MemoryTracker::kUnmanaged
)),
1366 memory_tracker_(memory_tracker
),
1367 feature_info_(feature_info
),
1368 framebuffer_manager_(NULL
),
1369 max_texture_size_(max_texture_size
),
1370 max_cube_map_texture_size_(max_cube_map_texture_size
),
1371 max_rectangle_texture_size_(max_rectangle_texture_size
),
1372 max_3d_texture_size_(max_3d_texture_size
),
1373 max_levels_(ComputeMipMapCount(GL_TEXTURE_2D
,
1377 max_cube_map_levels_(ComputeMipMapCount(GL_TEXTURE_CUBE_MAP
,
1378 max_cube_map_texture_size
,
1379 max_cube_map_texture_size
,
1380 max_cube_map_texture_size
)),
1381 max_3d_levels_(ComputeMipMapCount(GL_TEXTURE_3D
,
1382 // Same as GL_TEXTURE_2D_ARRAY
1383 max_3d_texture_size
,
1384 max_3d_texture_size
,
1385 max_3d_texture_size
)),
1386 use_default_textures_(use_default_textures
),
1387 num_unrenderable_textures_(0),
1388 num_unsafe_textures_(0),
1389 num_uncleared_mips_(0),
1392 have_context_(true) {
1393 for (int ii
= 0; ii
< kNumDefaultTextures
; ++ii
) {
1394 black_texture_ids_
[ii
] = 0;
1398 bool TextureManager::Initialize() {
1399 // TODO(gman): The default textures have to be real textures, not the 0
1400 // texture because we simulate non shared resources on top of shared
1401 // resources and all contexts that share resource share the same default
1403 default_textures_
[kTexture2D
] = CreateDefaultAndBlackTextures(
1404 GL_TEXTURE_2D
, &black_texture_ids_
[kTexture2D
]);
1405 default_textures_
[kCubeMap
] = CreateDefaultAndBlackTextures(
1406 GL_TEXTURE_CUBE_MAP
, &black_texture_ids_
[kCubeMap
]);
1408 if (feature_info_
->feature_flags().oes_egl_image_external
) {
1409 default_textures_
[kExternalOES
] = CreateDefaultAndBlackTextures(
1410 GL_TEXTURE_EXTERNAL_OES
, &black_texture_ids_
[kExternalOES
]);
1413 if (feature_info_
->feature_flags().arb_texture_rectangle
) {
1414 default_textures_
[kRectangleARB
] = CreateDefaultAndBlackTextures(
1415 GL_TEXTURE_RECTANGLE_ARB
, &black_texture_ids_
[kRectangleARB
]);
1418 // When created from InProcessCommandBuffer, we won't have a |memory_tracker_|
1419 // so don't register a dump provider.
1420 if (memory_tracker_
) {
1421 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
1422 this, base::ThreadTaskRunnerHandle::Get());
1428 scoped_refptr
<TextureRef
>
1429 TextureManager::CreateDefaultAndBlackTextures(
1431 GLuint
* black_texture
) {
1432 static uint8 black
[] = {0, 0, 0, 255};
1434 // Sampling a texture not associated with any EGLImage sibling will return
1435 // black values according to the spec.
1436 bool needs_initialization
= (target
!= GL_TEXTURE_EXTERNAL_OES
);
1437 bool needs_faces
= (target
== GL_TEXTURE_CUBE_MAP
);
1439 // Make default textures and texture for replacing non-renderable textures.
1441 const int num_ids
= use_default_textures_
? 2 : 1;
1442 glGenTextures(num_ids
, ids
);
1443 for (int ii
= 0; ii
< num_ids
; ++ii
) {
1444 glBindTexture(target
, ids
[ii
]);
1445 if (needs_initialization
) {
1447 for (int jj
= 0; jj
< GLES2Util::kNumFaces
; ++jj
) {
1448 glTexImage2D(GLES2Util::IndexToGLFaceTarget(jj
), 0, GL_RGBA
, 1, 1, 0,
1449 GL_RGBA
, GL_UNSIGNED_BYTE
, black
);
1452 glTexImage2D(target
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
,
1453 GL_UNSIGNED_BYTE
, black
);
1457 glBindTexture(target
, 0);
1459 scoped_refptr
<TextureRef
> default_texture
;
1460 if (use_default_textures_
) {
1461 default_texture
= TextureRef::Create(this, 0, ids
[1]);
1462 SetTarget(default_texture
.get(), target
);
1464 for (int ii
= 0; ii
< GLES2Util::kNumFaces
; ++ii
) {
1465 SetLevelInfo(default_texture
.get(), GLES2Util::IndexToGLFaceTarget(ii
),
1466 0, GL_RGBA
, 1, 1, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
,
1470 if (needs_initialization
) {
1471 SetLevelInfo(default_texture
.get(), GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 1,
1472 0, GL_RGBA
, GL_UNSIGNED_BYTE
, gfx::Rect(1, 1));
1474 SetLevelInfo(default_texture
.get(), GL_TEXTURE_EXTERNAL_OES
, 0, GL_RGBA
,
1475 1, 1, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, gfx::Rect(1, 1));
1480 *black_texture
= ids
[0];
1481 return default_texture
;
1484 bool TextureManager::ValidForTarget(
1485 GLenum target
, GLint level
, GLsizei width
, GLsizei height
, GLsizei depth
) {
1486 GLsizei max_size
= MaxSizeForTarget(target
) >> level
;
1487 return level
>= 0 &&
1491 level
< MaxLevelsForTarget(target
) &&
1492 width
<= max_size
&&
1493 height
<= max_size
&&
1494 depth
<= max_size
&&
1495 (level
== 0 || feature_info_
->feature_flags().npot_ok
||
1496 (!GLES2Util::IsNPOT(width
) &&
1497 !GLES2Util::IsNPOT(height
) &&
1498 !GLES2Util::IsNPOT(depth
))) &&
1499 (target
!= GL_TEXTURE_CUBE_MAP
|| (width
== height
&& depth
== 1)) &&
1500 (target
!= GL_TEXTURE_2D
|| (depth
== 1));
1503 void TextureManager::SetTarget(TextureRef
* ref
, GLenum target
) {
1506 ->SetTarget(feature_info_
.get(), target
, MaxLevelsForTarget(target
));
1509 void TextureManager::SetLevelClearedRect(TextureRef
* ref
,
1512 const gfx::Rect
& cleared_rect
) {
1514 ref
->texture()->SetLevelClearedRect(target
, level
, cleared_rect
);
1517 void TextureManager::SetLevelCleared(TextureRef
* ref
,
1522 ref
->texture()->SetLevelCleared(target
, level
, cleared
);
1525 bool TextureManager::ClearRenderableLevels(
1526 GLES2Decoder
* decoder
, TextureRef
* ref
) {
1528 return ref
->texture()->ClearRenderableLevels(decoder
);
1531 bool TextureManager::ClearTextureLevel(
1532 GLES2Decoder
* decoder
, TextureRef
* ref
,
1533 GLenum target
, GLint level
) {
1535 Texture
* texture
= ref
->texture();
1536 if (texture
->num_uncleared_mips() == 0) {
1539 bool result
= texture
->ClearLevel(decoder
, target
, level
);
1540 texture
->UpdateCleared();
1544 void TextureManager::SetLevelInfo(TextureRef
* ref
,
1547 GLenum internal_format
,
1554 const gfx::Rect
& cleared_rect
) {
1555 DCHECK(gfx::Rect(width
, height
).Contains(cleared_rect
));
1557 Texture
* texture
= ref
->texture();
1559 texture
->GetMemTracker()->TrackMemFree(texture
->estimated_size());
1560 texture
->SetLevelInfo(feature_info_
.get(), target
, level
, internal_format
,
1561 width
, height
, depth
, border
, format
, type
,
1563 texture
->GetMemTracker()->TrackMemAlloc(texture
->estimated_size());
1566 Texture
* TextureManager::Produce(TextureRef
* ref
) {
1568 return ref
->texture();
1571 TextureRef
* TextureManager::Consume(
1575 scoped_refptr
<TextureRef
> ref(new TextureRef(this, client_id
, texture
));
1576 bool result
= textures_
.insert(std::make_pair(client_id
, ref
)).second
;
1581 void TextureManager::SetParameteri(
1582 const char* function_name
, ErrorState
* error_state
,
1583 TextureRef
* ref
, GLenum pname
, GLint param
) {
1584 DCHECK(error_state
);
1586 Texture
* texture
= ref
->texture();
1587 GLenum result
= texture
->SetParameteri(feature_info_
.get(), pname
, param
);
1588 if (result
!= GL_NO_ERROR
) {
1589 if (result
== GL_INVALID_ENUM
) {
1590 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1591 error_state
, function_name
, param
, "param");
1593 ERRORSTATE_SET_GL_ERROR_INVALID_PARAMI(
1594 error_state
, result
, function_name
, pname
, param
);
1597 // Texture tracking pools exist only for the command decoder, so
1598 // do not pass them on to the native GL implementation.
1599 if (pname
!= GL_TEXTURE_POOL_CHROMIUM
) {
1600 glTexParameteri(texture
->target(), pname
, param
);
1605 void TextureManager::SetParameterf(
1606 const char* function_name
, ErrorState
* error_state
,
1607 TextureRef
* ref
, GLenum pname
, GLfloat param
) {
1608 DCHECK(error_state
);
1610 Texture
* texture
= ref
->texture();
1611 GLenum result
= texture
->SetParameterf(feature_info_
.get(), pname
, param
);
1612 if (result
!= GL_NO_ERROR
) {
1613 if (result
== GL_INVALID_ENUM
) {
1614 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1615 error_state
, function_name
, pname
, "pname");
1617 ERRORSTATE_SET_GL_ERROR_INVALID_PARAMF(
1618 error_state
, result
, function_name
, pname
, param
);
1621 // Texture tracking pools exist only for the command decoder, so
1622 // do not pass them on to the native GL implementation.
1623 if (pname
!= GL_TEXTURE_POOL_CHROMIUM
) {
1624 glTexParameterf(texture
->target(), pname
, param
);
1629 bool TextureManager::MarkMipmapsGenerated(TextureRef
* ref
) {
1631 Texture
* texture
= ref
->texture();
1632 texture
->GetMemTracker()->TrackMemFree(texture
->estimated_size());
1633 bool result
= texture
->MarkMipmapsGenerated(feature_info_
.get());
1634 texture
->GetMemTracker()->TrackMemAlloc(texture
->estimated_size());
1638 TextureRef
* TextureManager::CreateTexture(
1639 GLuint client_id
, GLuint service_id
) {
1640 DCHECK_NE(0u, service_id
);
1641 scoped_refptr
<TextureRef
> ref(TextureRef::Create(
1642 this, client_id
, service_id
));
1643 std::pair
<TextureMap::iterator
, bool> result
=
1644 textures_
.insert(std::make_pair(client_id
, ref
));
1645 DCHECK(result
.second
);
1649 TextureRef
* TextureManager::GetTexture(
1650 GLuint client_id
) const {
1651 TextureMap::const_iterator it
= textures_
.find(client_id
);
1652 return it
!= textures_
.end() ? it
->second
.get() : NULL
;
1655 void TextureManager::RemoveTexture(GLuint client_id
) {
1656 TextureMap::iterator it
= textures_
.find(client_id
);
1657 if (it
!= textures_
.end()) {
1658 it
->second
->reset_client_id();
1659 textures_
.erase(it
);
1663 void TextureManager::StartTracking(TextureRef
* ref
) {
1664 Texture
* texture
= ref
->texture();
1666 num_uncleared_mips_
+= texture
->num_uncleared_mips();
1667 if (!texture
->SafeToRenderFrom())
1668 ++num_unsafe_textures_
;
1669 if (!texture
->CanRender(feature_info_
.get()))
1670 ++num_unrenderable_textures_
;
1671 if (texture
->HasImages())
1675 void TextureManager::StopTracking(TextureRef
* ref
) {
1676 if (ref
->num_observers()) {
1677 for (unsigned int i
= 0; i
< destruction_observers_
.size(); i
++) {
1678 destruction_observers_
[i
]->OnTextureRefDestroying(ref
);
1680 DCHECK_EQ(ref
->num_observers(), 0);
1683 Texture
* texture
= ref
->texture();
1686 if (texture
->HasImages()) {
1687 DCHECK_NE(0, num_images_
);
1690 if (!texture
->CanRender(feature_info_
.get())) {
1691 DCHECK_NE(0, num_unrenderable_textures_
);
1692 --num_unrenderable_textures_
;
1694 if (!texture
->SafeToRenderFrom()) {
1695 DCHECK_NE(0, num_unsafe_textures_
);
1696 --num_unsafe_textures_
;
1698 num_uncleared_mips_
-= texture
->num_uncleared_mips();
1699 DCHECK_GE(num_uncleared_mips_
, 0);
1702 MemoryTypeTracker
* TextureManager::GetMemTracker(GLenum tracking_pool
) {
1703 switch (tracking_pool
) {
1704 case GL_TEXTURE_POOL_MANAGED_CHROMIUM
:
1705 return memory_tracker_managed_
.get();
1707 case GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
:
1708 return memory_tracker_unmanaged_
.get();
1717 Texture
* TextureManager::GetTextureForServiceId(GLuint service_id
) const {
1718 // This doesn't need to be fast. It's only used during slow queries.
1719 for (TextureMap::const_iterator it
= textures_
.begin();
1720 it
!= textures_
.end(); ++it
) {
1721 Texture
* texture
= it
->second
->texture();
1722 if (texture
->service_id() == service_id
)
1728 GLsizei
TextureManager::ComputeMipMapCount(GLenum target
,
1733 case GL_TEXTURE_EXTERNAL_OES
:
1737 base::bits::Log2Floor(std::max(std::max(width
, height
), depth
));
1741 void TextureManager::SetLevelImage(
1745 gfx::GLImage
* image
) {
1747 ref
->texture()->SetLevelImage(feature_info_
.get(), target
, level
, image
);
1750 size_t TextureManager::GetSignatureSize() const {
1751 return sizeof(TextureTag
) + sizeof(TextureSignature
);
1754 void TextureManager::AddToSignature(
1758 std::string
* signature
) const {
1759 ref
->texture()->AddToSignature(feature_info_
.get(), target
, level
, signature
);
1762 void TextureManager::UpdateSafeToRenderFrom(int delta
) {
1763 num_unsafe_textures_
+= delta
;
1764 DCHECK_GE(num_unsafe_textures_
, 0);
1767 void TextureManager::UpdateUnclearedMips(int delta
) {
1768 num_uncleared_mips_
+= delta
;
1769 DCHECK_GE(num_uncleared_mips_
, 0);
1772 void TextureManager::UpdateCanRenderCondition(
1773 Texture::CanRenderCondition old_condition
,
1774 Texture::CanRenderCondition new_condition
) {
1775 if (old_condition
== Texture::CAN_RENDER_NEVER
||
1776 (old_condition
== Texture::CAN_RENDER_ONLY_IF_NPOT
&&
1777 !feature_info_
->feature_flags().npot_ok
)) {
1778 DCHECK_GT(num_unrenderable_textures_
, 0);
1779 --num_unrenderable_textures_
;
1781 if (new_condition
== Texture::CAN_RENDER_NEVER
||
1782 (new_condition
== Texture::CAN_RENDER_ONLY_IF_NPOT
&&
1783 !feature_info_
->feature_flags().npot_ok
))
1784 ++num_unrenderable_textures_
;
1787 void TextureManager::UpdateNumImages(int delta
) {
1788 num_images_
+= delta
;
1789 DCHECK_GE(num_images_
, 0);
1792 void TextureManager::IncFramebufferStateChangeCount() {
1793 if (framebuffer_manager_
)
1794 framebuffer_manager_
->IncFramebufferStateChangeCount();
1797 bool TextureManager::ValidateFormatAndTypeCombination(
1798 ErrorState
* error_state
, const char* function_name
, GLenum format
,
1800 // TODO(zmo): now this is only called by GLES2DecoderImpl::DoCopyTexImage2D
1801 // and is incorrect for ES3. Fix this.
1802 if (!g_format_type_validator
.Get().IsValid(format
, format
, type
)) {
1803 ERRORSTATE_SET_GL_ERROR(
1804 error_state
, GL_INVALID_OPERATION
, function_name
,
1805 (std::string("invalid type ") +
1806 GLES2Util::GetStringEnum(type
) + " for format " +
1807 GLES2Util::GetStringEnum(format
)).c_str());
1813 bool TextureManager::ValidateTextureParameters(
1814 ErrorState
* error_state
, const char* function_name
,
1815 GLenum format
, GLenum type
, GLenum internal_format
, GLint level
) {
1816 const Validators
* validators
= feature_info_
->validators();
1817 if (!validators
->texture_format
.IsValid(format
)) {
1818 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1819 error_state
, function_name
, format
, "format");
1822 if (!validators
->pixel_type
.IsValid(type
)) {
1823 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1824 error_state
, function_name
, type
, "type");
1827 if (!g_format_type_validator
.Get().IsValid(internal_format
, format
, type
)) {
1828 ERRORSTATE_SET_GL_ERROR(
1829 error_state
, GL_INVALID_OPERATION
, function_name
,
1830 "invalid internalformat/format/type combination");
1833 // For TexSubImage calls, internal_format isn't part of the parameters,
1834 // so its validation needs to be after the internal_format/format/type
1835 // combination validation. Otherwise, an unexpected INVALID_ENUM could be
1836 // generated instead of INVALID_OPERATION.
1837 if (!validators
->texture_internal_format
.IsValid(internal_format
)) {
1838 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1839 error_state
, function_name
, internal_format
, "internal_format");
1842 if (!feature_info_
->IsES3Enabled()) {
1843 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
1844 if ((channels
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0 && level
) {
1845 ERRORSTATE_SET_GL_ERROR(
1846 error_state
, GL_INVALID_OPERATION
, function_name
,
1847 (std::string("invalid format ") + GLES2Util::GetStringEnum(format
) +
1848 " for level != 0").c_str());
1855 // Gets the texture id for a given target.
1856 TextureRef
* TextureManager::GetTextureInfoForTarget(
1857 ContextState
* state
, GLenum target
) {
1858 TextureUnit
& unit
= state
->texture_units
[state
->active_texture_unit
];
1859 TextureRef
* texture
= NULL
;
1862 texture
= unit
.bound_texture_2d
.get();
1864 case GL_TEXTURE_CUBE_MAP
:
1865 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
1866 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
1867 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
1868 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
1869 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
1870 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
1871 texture
= unit
.bound_texture_cube_map
.get();
1873 case GL_TEXTURE_EXTERNAL_OES
:
1874 texture
= unit
.bound_texture_external_oes
.get();
1876 case GL_TEXTURE_RECTANGLE_ARB
:
1877 texture
= unit
.bound_texture_rectangle_arb
.get();
1880 texture
= unit
.bound_texture_3d
.get();
1882 case GL_TEXTURE_2D_ARRAY
:
1883 texture
= unit
.bound_texture_2d_array
.get();
1892 TextureRef
* TextureManager::GetTextureInfoForTargetUnlessDefault(
1893 ContextState
* state
, GLenum target
) {
1894 TextureRef
* texture
= GetTextureInfoForTarget(state
, target
);
1897 if (texture
== GetDefaultTextureInfo(target
))
1902 bool TextureManager::ValidateTexImage(
1903 ContextState
* state
,
1904 const char* function_name
,
1905 const DoTexImageArguments
& args
,
1906 TextureRef
** texture_ref
) {
1907 ErrorState
* error_state
= state
->GetErrorState();
1908 const Validators
* validators
= feature_info_
->validators();
1909 if (((args
.command_type
== DoTexImageArguments::kTexImage2D
) &&
1910 !validators
->texture_target
.IsValid(args
.target
)) ||
1911 ((args
.command_type
== DoTexImageArguments::kTexImage3D
) &&
1912 !validators
->texture_3_d_target
.IsValid(args
.target
))) {
1913 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1914 error_state
, function_name
, args
.target
, "target");
1917 if (!ValidateTextureParameters(
1918 error_state
, function_name
, args
.format
, args
.type
,
1919 args
.internal_format
, args
.level
)) {
1922 if (!ValidForTarget(args
.target
, args
.level
,
1923 args
.width
, args
.height
, args
.depth
) ||
1925 ERRORSTATE_SET_GL_ERROR(
1926 error_state
, GL_INVALID_VALUE
, function_name
,
1927 "dimensions out of range");
1930 if ((GLES2Util::GetChannelsForFormat(args
.format
) &
1931 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0 && args
.pixels
1932 && !feature_info_
->IsES3Enabled()) {
1933 ERRORSTATE_SET_GL_ERROR(
1934 error_state
, GL_INVALID_OPERATION
,
1935 function_name
, "can not supply data for depth or stencil textures");
1939 TextureRef
* local_texture_ref
= GetTextureInfoForTarget(state
, args
.target
);
1940 if (!local_texture_ref
) {
1941 ERRORSTATE_SET_GL_ERROR(
1942 error_state
, GL_INVALID_OPERATION
, function_name
,
1943 "unknown texture for target");
1946 if (local_texture_ref
->texture()->IsImmutable()) {
1947 ERRORSTATE_SET_GL_ERROR(
1948 error_state
, GL_INVALID_OPERATION
, function_name
,
1949 "texture is immutable");
1953 if (!memory_tracker_managed_
->EnsureGPUMemoryAvailable(args
.pixels_size
)) {
1954 ERRORSTATE_SET_GL_ERROR(error_state
, GL_OUT_OF_MEMORY
, function_name
,
1959 // Write the TextureReference since this is valid.
1960 *texture_ref
= local_texture_ref
;
1964 void TextureManager::ValidateAndDoTexImage(
1965 DecoderTextureState
* texture_state
,
1966 ContextState
* state
,
1967 DecoderFramebufferState
* framebuffer_state
,
1968 const char* function_name
,
1969 const DoTexImageArguments
& args
) {
1970 TextureRef
* texture_ref
;
1971 if (!ValidateTexImage(state
, function_name
, args
, &texture_ref
)) {
1975 DoTexImage(texture_state
, state
->GetErrorState(), framebuffer_state
,
1976 function_name
, texture_ref
, args
);
1979 GLenum
TextureManager::AdjustTexFormat(GLenum format
) const {
1980 // TODO(bajones): GLES 3 allows for internal format and format to differ.
1981 // This logic may need to change as a result.
1982 if (gfx::GetGLImplementation() == gfx::kGLImplementationDesktopGL
) {
1983 if (format
== GL_SRGB_EXT
)
1985 if (format
== GL_SRGB_ALPHA_EXT
)
1991 void TextureManager::DoTexImage(
1992 DecoderTextureState
* texture_state
,
1993 ErrorState
* error_state
,
1994 DecoderFramebufferState
* framebuffer_state
,
1995 const char* function_name
,
1996 TextureRef
* texture_ref
,
1997 const DoTexImageArguments
& args
) {
1998 Texture
* texture
= texture_ref
->texture();
1999 GLsizei tex_width
= 0;
2000 GLsizei tex_height
= 0;
2001 GLsizei tex_depth
= 0;
2002 GLenum tex_type
= 0;
2003 GLenum tex_format
= 0;
2004 bool level_is_same
=
2005 texture
->GetLevelSize(
2006 args
.target
, args
.level
, &tex_width
, &tex_height
, &tex_depth
) &&
2007 texture
->GetLevelType(args
.target
, args
.level
, &tex_type
, &tex_format
) &&
2008 args
.width
== tex_width
&& args
.height
== tex_height
&&
2009 args
.depth
== tex_depth
&& args
.type
== tex_type
&&
2010 args
.format
== tex_format
;
2012 if (level_is_same
&& !args
.pixels
) {
2013 // Just set the level texture but mark the texture as uncleared.
2014 SetLevelInfo(texture_ref
, args
.target
, args
.level
, args
.internal_format
,
2015 args
.width
, args
.height
, args
.depth
, args
.border
, args
.format
,
2016 args
.type
, gfx::Rect());
2017 texture_state
->tex_image_failed
= false;
2021 if (texture
->IsAttachedToFramebuffer()) {
2022 framebuffer_state
->clear_state_dirty
= true;
2025 if (texture_state
->texsubimage_faster_than_teximage
&&
2026 level_is_same
&& args
.pixels
) {
2028 ScopedTextureUploadTimer
timer(texture_state
);
2029 if (args
.command_type
== DoTexImageArguments::kTexImage3D
) {
2030 glTexSubImage3D(args
.target
, args
.level
, 0, 0, 0,
2031 args
.width
, args
.height
, args
.depth
,
2032 args
.format
, args
.type
, args
.pixels
);
2034 glTexSubImage2D(args
.target
, args
.level
, 0, 0, args
.width
, args
.height
,
2035 AdjustTexFormat(args
.format
), args
.type
, args
.pixels
);
2038 SetLevelCleared(texture_ref
, args
.target
, args
.level
, true);
2039 texture_state
->tex_image_failed
= false;
2043 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state
, function_name
);
2045 ScopedTextureUploadTimer
timer(texture_state
);
2046 if (args
.command_type
== DoTexImageArguments::kTexImage3D
) {
2047 glTexImage3D(args
.target
, args
.level
, args
.internal_format
, args
.width
,
2048 args
.height
, args
.depth
, args
.border
, args
.format
,
2049 args
.type
, args
.pixels
);
2051 glTexImage2D(args
.target
, args
.level
, args
.internal_format
, args
.width
,
2052 args
.height
, args
.border
, AdjustTexFormat(args
.format
),
2053 args
.type
, args
.pixels
);
2056 GLenum error
= ERRORSTATE_PEEK_GL_ERROR(error_state
, function_name
);
2057 if (error
== GL_NO_ERROR
) {
2059 texture_ref
, args
.target
, args
.level
, args
.internal_format
, args
.width
,
2060 args
.height
, args
.depth
, args
.border
, args
.format
, args
.type
,
2061 args
.pixels
!= NULL
? gfx::Rect(args
.width
, args
.height
) : gfx::Rect());
2062 texture_state
->tex_image_failed
= false;
2066 ScopedTextureUploadTimer::ScopedTextureUploadTimer(
2067 DecoderTextureState
* texture_state
)
2068 : texture_state_(texture_state
),
2069 begin_time_(base::TimeTicks::Now()) {
2072 ScopedTextureUploadTimer::~ScopedTextureUploadTimer() {
2073 texture_state_
->texture_upload_count
++;
2074 texture_state_
->total_texture_upload_time
+=
2075 base::TimeTicks::Now() - begin_time_
;
2078 bool TextureManager::OnMemoryDump(const base::trace_event::MemoryDumpArgs
& args
,
2079 base::trace_event::ProcessMemoryDump
* pmd
) {
2080 for (const auto& resource
: textures_
) {
2081 // Only dump memory info for textures actually owned by this TextureManager.
2082 DumpTextureRef(pmd
, resource
.second
.get());
2085 // Also dump TextureManager internal textures, if allocated.
2086 for (int i
= 0; i
< kNumDefaultTextures
; i
++) {
2087 if (default_textures_
[i
]) {
2088 DumpTextureRef(pmd
, default_textures_
[i
].get());
2095 void TextureManager::DumpTextureRef(base::trace_event::ProcessMemoryDump
* pmd
,
2097 uint32_t size
= ref
->texture()->estimated_size();
2099 // Ignore unallocated texture IDs.
2103 std::string dump_name
=
2104 base::StringPrintf("gl/client_%d/textures/texture_%d",
2105 memory_tracker_
->ClientId(), ref
->client_id());
2107 base::trace_event::MemoryAllocatorDump
* dump
=
2108 pmd
->CreateAllocatorDump(dump_name
);
2109 dump
->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize
,
2110 base::trace_event::MemoryAllocatorDump::kUnitsBytes
,
2111 static_cast<uint64_t>(size
));
2113 // Add the |client_guid| which expresses shared ownership with the client
2115 auto client_guid
= gfx::GetGLTextureGUIDForTracing(
2116 memory_tracker_
->ClientTracingId(), ref
->client_id());
2117 pmd
->CreateSharedGlobalAllocatorDump(client_guid
);
2118 pmd
->AddOwnershipEdge(dump
->guid(), client_guid
);
2120 // Add a |service_guid| which expresses shared ownership between the various
2122 // TODO(ericrk): May need to ensure uniqueness using GLShareGroup and
2123 // potentially cross-share-group sharing via EGLImages. crbug.com/512534
2125 gfx::GetGLTextureGUIDForTracing(0, ref
->texture()->service_id());
2126 pmd
->CreateSharedGlobalAllocatorDump(service_guid
);
2128 int importance
= 0; // Default importance.
2129 // The link to the memory tracking |client_id| is given a higher importance
2131 if (ref
== ref
->texture()->memory_tracking_ref_
)
2134 pmd
->AddOwnershipEdge(client_guid
, service_guid
, importance
);
2136 // Dump all sub-levels held by the texture. They will appear below the main
2137 // gl/textures/client_X/texture_Y dump.
2138 ref
->texture()->DumpLevelMemory(pmd
, memory_tracker_
->ClientTracingId(),
2142 } // namespace gles2