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 if (static_cast<size_t>(base_level_
) >= face_infos_
[0].level_infos
.size()) {
593 // Can't generate mips for depth or stencil textures.
594 const Texture::LevelInfo
& base
= face_infos_
[0].level_infos
[base_level_
];
595 uint32 channels
= GLES2Util::GetChannelsForFormat(base
.format
);
596 if (channels
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) {
600 // TODO(gman): Check internal_format, format and type.
601 for (size_t ii
= 0; ii
< face_infos_
.size(); ++ii
) {
602 const LevelInfo
& info
= face_infos_
[ii
].level_infos
[base_level_
];
603 if ((info
.target
== 0) || (info
.width
!= base
.width
) ||
604 (info
.height
!= base
.height
) || (info
.depth
!= base
.depth
) ||
605 (info
.format
!= base
.format
) ||
606 (info
.internal_format
!= base
.internal_format
) ||
607 (info
.type
!= base
.type
) ||
608 feature_info
->validators()->compressed_texture_format
.IsValid(
609 info
.internal_format
) ||
617 bool Texture::TextureIsNPOT(GLsizei width
,
620 return (GLES2Util::IsNPOT(width
) ||
621 GLES2Util::IsNPOT(height
) ||
622 GLES2Util::IsNPOT(depth
));
625 bool Texture::TextureFaceComplete(const Texture::LevelInfo
& first_face
,
628 GLenum internal_format
,
634 bool complete
= (target
!= 0 && depth
== 1);
635 if (face_index
!= 0) {
636 complete
&= (width
== first_face
.width
&&
637 height
== first_face
.height
&&
638 internal_format
== first_face
.internal_format
&&
639 format
== first_face
.format
&&
640 type
== first_face
.type
);
645 bool Texture::TextureMipComplete(const Texture::LevelInfo
& level0_face
,
648 GLenum internal_format
,
654 bool complete
= (target
!= 0);
656 const GLsizei mip_width
= std::max(1, level0_face
.width
>> level
);
657 const GLsizei mip_height
= std::max(1, level0_face
.height
>> level
);
658 const GLsizei mip_depth
= std::max(1, level0_face
.depth
>> level
);
660 complete
&= (width
== mip_width
&&
661 height
== mip_height
&&
662 depth
== mip_depth
&&
663 internal_format
== level0_face
.internal_format
&&
664 format
== level0_face
.format
&&
665 type
== level0_face
.type
);
670 void Texture::SetLevelClearedRect(GLenum target
,
672 const gfx::Rect
& cleared_rect
) {
674 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
675 DCHECK_LT(static_cast<size_t>(face_index
),
677 DCHECK_LT(static_cast<size_t>(level
),
678 face_infos_
[face_index
].level_infos
.size());
679 Texture::LevelInfo
& info
=
680 face_infos_
[face_index
].level_infos
[level
];
681 UpdateMipCleared(&info
, info
.width
, info
.height
, cleared_rect
);
685 void Texture::SetLevelCleared(GLenum target
, GLint level
, bool cleared
) {
687 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
688 DCHECK_LT(static_cast<size_t>(face_index
), face_infos_
.size());
689 DCHECK_LT(static_cast<size_t>(level
),
690 face_infos_
[face_index
].level_infos
.size());
691 Texture::LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
692 UpdateMipCleared(&info
, info
.width
, info
.height
,
693 cleared
? gfx::Rect(info
.width
, info
.height
) : gfx::Rect());
697 void Texture::UpdateCleared() {
698 if (face_infos_
.empty()) {
702 const bool cleared
= (num_uncleared_mips_
== 0);
704 // If texture is uncleared and is attached to a framebuffer,
705 // that framebuffer must be marked possibly incomplete.
706 if (!cleared
&& IsAttachedToFramebuffer()) {
707 IncAllFramebufferStateChangeCount();
710 UpdateSafeToRenderFrom(cleared
);
713 void Texture::UpdateSafeToRenderFrom(bool cleared
) {
714 if (cleared_
== cleared
)
717 int delta
= cleared
? -1 : +1;
718 for (RefSet::iterator it
= refs_
.begin(); it
!= refs_
.end(); ++it
)
719 (*it
)->manager()->UpdateSafeToRenderFrom(delta
);
722 void Texture::UpdateMipCleared(LevelInfo
* info
,
725 const gfx::Rect
& cleared_rect
) {
726 bool was_cleared
= info
->cleared_rect
== gfx::Rect(info
->width
, info
->height
);
728 info
->height
= height
;
729 info
->cleared_rect
= cleared_rect
;
730 bool cleared
= info
->cleared_rect
== gfx::Rect(info
->width
, info
->height
);
731 if (cleared
== was_cleared
)
733 int delta
= cleared
? -1 : +1;
734 num_uncleared_mips_
+= delta
;
735 for (RefSet::iterator it
= refs_
.begin(); it
!= refs_
.end(); ++it
)
736 (*it
)->manager()->UpdateUnclearedMips(delta
);
739 void Texture::UpdateCanRenderCondition() {
740 CanRenderCondition can_render_condition
= GetCanRenderCondition();
741 if (can_render_condition_
== can_render_condition
)
743 for (RefSet::iterator it
= refs_
.begin(); it
!= refs_
.end(); ++it
)
744 (*it
)->manager()->UpdateCanRenderCondition(can_render_condition_
,
745 can_render_condition
);
746 can_render_condition_
= can_render_condition
;
749 void Texture::UpdateHasImages() {
750 if (face_infos_
.empty())
753 bool has_images
= false;
754 for (size_t ii
= 0; ii
< face_infos_
.size(); ++ii
) {
755 for (size_t jj
= 0; jj
< face_infos_
[ii
].level_infos
.size(); ++jj
) {
756 const Texture::LevelInfo
& info
= face_infos_
[ii
].level_infos
[jj
];
757 if (info
.image
.get() != NULL
) {
764 if (has_images_
== has_images
)
766 has_images_
= has_images
;
767 int delta
= has_images
? +1 : -1;
768 for (RefSet::iterator it
= refs_
.begin(); it
!= refs_
.end(); ++it
)
769 (*it
)->manager()->UpdateNumImages(delta
);
772 void Texture::IncAllFramebufferStateChangeCount() {
773 for (RefSet::iterator it
= refs_
.begin(); it
!= refs_
.end(); ++it
)
774 (*it
)->manager()->IncFramebufferStateChangeCount();
777 void Texture::SetLevelInfo(const FeatureInfo
* feature_info
,
780 GLenum internal_format
,
787 const gfx::Rect
& cleared_rect
) {
789 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
790 DCHECK_LT(static_cast<size_t>(face_index
),
792 DCHECK_LT(static_cast<size_t>(level
),
793 face_infos_
[face_index
].level_infos
.size());
795 DCHECK_GE(height
, 0);
797 Texture::LevelInfo
& info
=
798 face_infos_
[face_index
].level_infos
[level
];
800 // Update counters only if any attributes have changed. Counters are
801 // comparisons between the old and new values so it must be done before any
802 // assignment has been done to the LevelInfo.
803 if (info
.target
!= target
||
804 info
.internal_format
!= internal_format
||
805 info
.width
!= width
||
806 info
.height
!= height
||
807 info
.depth
!= depth
||
808 info
.format
!= format
||
811 // Calculate the mip level count.
812 face_infos_
[face_index
].num_mip_levels
=
813 TextureManager::ComputeMipMapCount(target_
, width
, height
, depth
);
815 // Update NPOT face count for the first level.
816 bool prev_npot
= TextureIsNPOT(info
.width
, info
.height
, info
.depth
);
817 bool now_npot
= TextureIsNPOT(width
, height
, depth
);
818 if (prev_npot
!= now_npot
)
819 num_npot_faces_
+= now_npot
? 1 : -1;
821 // Signify that level 0 has been changed, so they need to be reverified.
822 texture_level0_dirty_
= true;
825 // Signify that at least one of the mips has changed.
826 texture_mips_dirty_
= true;
829 info
.target
= target
;
831 info
.internal_format
= internal_format
;
833 info
.border
= border
;
834 info
.format
= format
;
838 UpdateMipCleared(&info
, width
, height
, cleared_rect
);
840 estimated_size_
-= info
.estimated_size
;
841 GLES2Util::ComputeImageDataSizes(
842 width
, height
, 1, format
, type
, 4, &info
.estimated_size
, NULL
, NULL
);
843 estimated_size_
+= info
.estimated_size
;
845 max_level_set_
= std::max(max_level_set_
, level
);
846 Update(feature_info
);
848 UpdateCanRenderCondition();
850 if (IsAttachedToFramebuffer()) {
851 // TODO(gman): If textures tracked which framebuffers they were attached to
852 // we could just mark those framebuffers as not complete.
853 IncAllFramebufferStateChangeCount();
857 bool Texture::ValidForTexture(
867 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
868 if (level
>= 0 && face_index
< face_infos_
.size() &&
869 static_cast<size_t>(level
) < face_infos_
[face_index
].level_infos
.size()) {
870 const LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
874 return SafeAddInt32(xoffset
, width
, &max_x
) &&
875 SafeAddInt32(yoffset
, height
, &max_y
) &&
876 SafeAddInt32(zoffset
, depth
, &max_z
) &&
880 max_x
<= info
.width
&&
881 max_y
<= info
.height
&&
882 max_z
<= info
.depth
&&
888 bool Texture::GetLevelSize(
889 GLint target
, GLint level
,
890 GLsizei
* width
, GLsizei
* height
, GLsizei
* depth
) const {
893 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
894 if (level
>= 0 && face_index
< face_infos_
.size() &&
895 static_cast<size_t>(level
) < face_infos_
[face_index
].level_infos
.size()) {
896 const LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
897 if (info
.target
!= 0) {
899 *height
= info
.height
;
908 bool Texture::GetLevelType(
909 GLint target
, GLint level
, GLenum
* type
, GLenum
* internal_format
) const {
911 DCHECK(internal_format
);
912 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
913 if (level
>= 0 && face_index
< face_infos_
.size() &&
914 static_cast<size_t>(level
) < face_infos_
[face_index
].level_infos
.size()) {
915 const LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
916 if (info
.target
!= 0) {
918 *internal_format
= info
.internal_format
;
925 GLenum
Texture::SetParameteri(
926 const FeatureInfo
* feature_info
, GLenum pname
, GLint param
) {
927 DCHECK(feature_info
);
929 if (target_
== GL_TEXTURE_EXTERNAL_OES
||
930 target_
== GL_TEXTURE_RECTANGLE_ARB
) {
931 if (pname
== GL_TEXTURE_MIN_FILTER
&&
932 (param
!= GL_NEAREST
&& param
!= GL_LINEAR
))
933 return GL_INVALID_ENUM
;
934 if ((pname
== GL_TEXTURE_WRAP_S
|| pname
== GL_TEXTURE_WRAP_T
) &&
935 param
!= GL_CLAMP_TO_EDGE
)
936 return GL_INVALID_ENUM
;
940 case GL_TEXTURE_MIN_LOD
:
941 case GL_TEXTURE_MAX_LOD
:
943 GLfloat fparam
= static_cast<GLfloat
>(param
);
944 return SetParameterf(feature_info
, pname
, fparam
);
946 case GL_TEXTURE_MIN_FILTER
:
947 if (!feature_info
->validators()->texture_min_filter_mode
.IsValid(param
)) {
948 return GL_INVALID_ENUM
;
952 case GL_TEXTURE_MAG_FILTER
:
953 if (!feature_info
->validators()->texture_mag_filter_mode
.IsValid(param
)) {
954 return GL_INVALID_ENUM
;
958 case GL_TEXTURE_POOL_CHROMIUM
:
959 if (!feature_info
->validators()->texture_pool
.IsValid(param
)) {
960 return GL_INVALID_ENUM
;
962 GetMemTracker()->TrackMemFree(estimated_size());
964 GetMemTracker()->TrackMemAlloc(estimated_size());
966 case GL_TEXTURE_WRAP_R
:
967 if (!feature_info
->validators()->texture_wrap_mode
.IsValid(param
)) {
968 return GL_INVALID_ENUM
;
972 case GL_TEXTURE_WRAP_S
:
973 if (!feature_info
->validators()->texture_wrap_mode
.IsValid(param
)) {
974 return GL_INVALID_ENUM
;
978 case GL_TEXTURE_WRAP_T
:
979 if (!feature_info
->validators()->texture_wrap_mode
.IsValid(param
)) {
980 return GL_INVALID_ENUM
;
984 case GL_TEXTURE_COMPARE_FUNC
:
985 if (!feature_info
->validators()->texture_compare_func
.IsValid(param
)) {
986 return GL_INVALID_ENUM
;
988 compare_func_
= param
;
990 case GL_TEXTURE_COMPARE_MODE
:
991 if (!feature_info
->validators()->texture_compare_mode
.IsValid(param
)) {
992 return GL_INVALID_ENUM
;
994 compare_mode_
= param
;
996 case GL_TEXTURE_BASE_LEVEL
:
998 return GL_INVALID_VALUE
;
1000 base_level_
= param
;
1002 case GL_TEXTURE_MAX_LEVEL
:
1004 return GL_INVALID_VALUE
;
1008 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
1010 return GL_INVALID_VALUE
;
1013 case GL_TEXTURE_USAGE_ANGLE
:
1014 if (!feature_info
->validators()->texture_usage
.IsValid(param
)) {
1015 return GL_INVALID_ENUM
;
1021 return GL_INVALID_ENUM
;
1023 Update(feature_info
);
1025 UpdateCanRenderCondition();
1029 GLenum
Texture::SetParameterf(
1030 const FeatureInfo
* feature_info
, GLenum pname
, GLfloat param
) {
1032 case GL_TEXTURE_MIN_FILTER
:
1033 case GL_TEXTURE_MAG_FILTER
:
1034 case GL_TEXTURE_POOL_CHROMIUM
:
1035 case GL_TEXTURE_WRAP_R
:
1036 case GL_TEXTURE_WRAP_S
:
1037 case GL_TEXTURE_WRAP_T
:
1038 case GL_TEXTURE_COMPARE_FUNC
:
1039 case GL_TEXTURE_COMPARE_MODE
:
1040 case GL_TEXTURE_BASE_LEVEL
:
1041 case GL_TEXTURE_MAX_LEVEL
:
1042 case GL_TEXTURE_USAGE_ANGLE
:
1044 GLint iparam
= static_cast<GLint
>(param
);
1045 return SetParameteri(feature_info
, pname
, iparam
);
1047 case GL_TEXTURE_MIN_LOD
:
1050 case GL_TEXTURE_MAX_LOD
:
1053 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
1055 return GL_INVALID_VALUE
;
1060 return GL_INVALID_ENUM
;
1065 void Texture::Update(const FeatureInfo
* feature_info
) {
1066 // Update npot status.
1067 // Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others
1068 npot_
= (target_
== GL_TEXTURE_EXTERNAL_OES
) || (num_npot_faces_
> 0);
1070 if (face_infos_
.empty()) {
1071 texture_complete_
= false;
1072 cube_complete_
= false;
1076 // Update texture_complete and cube_complete status.
1077 const Texture::FaceInfo
& first_face
= face_infos_
[0];
1078 const Texture::LevelInfo
& first_level
= first_face
.level_infos
[0];
1079 const GLsizei levels_needed
= first_face
.num_mip_levels
;
1082 max_level_set_
>= (levels_needed
- 1) && max_level_set_
>= 0;
1083 cube_complete_
= (face_infos_
.size() == 6) &&
1084 (first_level
.width
== first_level
.height
);
1086 if (first_level
.width
== 0 || first_level
.height
== 0) {
1087 texture_complete_
= false;
1088 } else if (first_level
.type
== GL_FLOAT
&&
1089 !feature_info
->feature_flags().enable_texture_float_linear
&&
1090 (min_filter_
!= GL_NEAREST_MIPMAP_NEAREST
||
1091 mag_filter_
!= GL_NEAREST
)) {
1092 texture_complete_
= false;
1093 } else if (first_level
.type
== GL_HALF_FLOAT_OES
&&
1094 !feature_info
->feature_flags().enable_texture_half_float_linear
&&
1095 (min_filter_
!= GL_NEAREST_MIPMAP_NEAREST
||
1096 mag_filter_
!= GL_NEAREST
)) {
1097 texture_complete_
= false;
1100 if (cube_complete_
&& texture_level0_dirty_
) {
1101 texture_level0_complete_
= true;
1102 for (size_t ii
= 0; ii
< face_infos_
.size(); ++ii
) {
1103 const Texture::LevelInfo
& level0
= face_infos_
[ii
].level_infos
[0];
1104 if (!TextureFaceComplete(first_level
,
1107 level0
.internal_format
,
1113 texture_level0_complete_
= false;
1117 texture_level0_dirty_
= false;
1119 cube_complete_
&= texture_level0_complete_
;
1121 if (texture_complete_
&& texture_mips_dirty_
) {
1122 texture_mips_complete_
= true;
1124 ii
< face_infos_
.size() && texture_mips_complete_
;
1126 const Texture::FaceInfo
& face_info
= face_infos_
[ii
];
1127 const Texture::LevelInfo
& level0
= face_info
.level_infos
[0];
1128 for (GLsizei jj
= 1; jj
< levels_needed
; ++jj
) {
1129 const Texture::LevelInfo
& level_info
= face_infos_
[ii
].level_infos
[jj
];
1130 if (!TextureMipComplete(level0
,
1133 level_info
.internal_format
,
1139 texture_mips_complete_
= false;
1144 texture_mips_dirty_
= false;
1146 texture_complete_
&= texture_mips_complete_
;
1149 bool Texture::ClearRenderableLevels(GLES2Decoder
* decoder
) {
1155 for (size_t ii
= 0; ii
< face_infos_
.size(); ++ii
) {
1156 const Texture::FaceInfo
& face_info
= face_infos_
[ii
];
1157 for (GLint jj
= 0; jj
< face_info
.num_mip_levels
; ++jj
) {
1158 const Texture::LevelInfo
& info
= face_info
.level_infos
[jj
];
1159 if (info
.target
!= 0) {
1160 if (!ClearLevel(decoder
, info
.target
, jj
)) {
1166 UpdateSafeToRenderFrom(true);
1170 gfx::Rect
Texture::GetLevelClearedRect(GLenum target
, GLint level
) const {
1171 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
1172 if (face_index
>= face_infos_
.size() ||
1173 level
>= static_cast<GLint
>(face_infos_
[face_index
].level_infos
.size())) {
1177 const Texture::LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
1179 return info
.cleared_rect
;
1182 bool Texture::IsLevelCleared(GLenum target
, GLint level
) const {
1183 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
1184 if (face_index
>= face_infos_
.size() ||
1185 level
>= static_cast<GLint
>(face_infos_
[face_index
].level_infos
.size())) {
1189 const Texture::LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
1191 return info
.cleared_rect
== gfx::Rect(info
.width
, info
.height
);
1194 void Texture::InitTextureMaxAnisotropyIfNeeded(GLenum target
) {
1195 if (texture_max_anisotropy_initialized_
)
1197 texture_max_anisotropy_initialized_
= true;
1198 GLfloat params
[] = { 1.0f
};
1199 glTexParameterfv(target
, GL_TEXTURE_MAX_ANISOTROPY_EXT
, params
);
1202 bool Texture::ClearLevel(
1203 GLES2Decoder
* decoder
, GLenum target
, GLint level
) {
1205 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
1206 if (face_index
>= face_infos_
.size() ||
1207 level
>= static_cast<GLint
>(face_infos_
[face_index
].level_infos
.size())) {
1211 Texture::LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
1213 DCHECK(target
== info
.target
);
1215 if (info
.target
== 0 ||
1216 info
.cleared_rect
== gfx::Rect(info
.width
, info
.height
) ||
1217 info
.width
== 0 || info
.height
== 0 || info
.depth
== 0) {
1221 // Clear all remaining sub regions.
1223 0, info
.cleared_rect
.x(), info
.cleared_rect
.right(), info
.width
};
1225 0, info
.cleared_rect
.y(), info
.cleared_rect
.bottom(), info
.height
};
1227 for (size_t j
= 0; j
< 3; ++j
) {
1228 for (size_t i
= 0; i
< 3; ++i
) {
1229 // Center of nine patch is already cleared.
1230 if (j
== 1 && i
== 1)
1233 gfx::Rect
rect(x
[i
], y
[j
], x
[i
+ 1] - x
[i
], y
[j
+ 1] - y
[j
]);
1237 // NOTE: It seems kind of gross to call back into the decoder for this
1238 // but only the decoder knows all the state (like unpack_alignment_)
1239 // that's needed to be able to call GL correctly.
1240 bool cleared
= decoder
->ClearLevel(this, info
.target
, info
.level
,
1241 info
.format
, info
.type
, rect
.x(),
1242 rect
.y(), rect
.width(), rect
.height());
1248 UpdateMipCleared(&info
, info
.width
, info
.height
,
1249 gfx::Rect(info
.width
, info
.height
));
1253 void Texture::SetLevelImage(
1254 const FeatureInfo
* feature_info
,
1257 gfx::GLImage
* image
) {
1258 DCHECK_GE(level
, 0);
1259 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
1260 DCHECK_LT(static_cast<size_t>(face_index
),
1261 face_infos_
.size());
1262 DCHECK_LT(static_cast<size_t>(level
),
1263 face_infos_
[face_index
].level_infos
.size());
1264 Texture::LevelInfo
& info
=
1265 face_infos_
[face_index
].level_infos
[level
];
1266 DCHECK_EQ(info
.target
, target
);
1267 DCHECK_EQ(info
.level
, level
);
1269 UpdateCanRenderCondition();
1272 // TODO(ericrk): Images may have complex sizing not accounted for by
1273 // |estimated_size_|, we should add logic here to update |estimated_size_|
1274 // based on the new GLImage. crbug.com/526298
1277 gfx::GLImage
* Texture::GetLevelImage(GLint target
, GLint level
) const {
1278 if (target
!= GL_TEXTURE_2D
&& target
!= GL_TEXTURE_EXTERNAL_OES
&&
1279 target
!= GL_TEXTURE_RECTANGLE_ARB
) {
1283 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
1284 if (level
>= 0 && face_index
< face_infos_
.size() &&
1285 static_cast<size_t>(level
) < face_infos_
[face_index
].level_infos
.size()) {
1286 const LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
1287 if (info
.target
!= 0) {
1288 return info
.image
.get();
1294 void Texture::OnWillModifyPixels() {
1295 gfx::GLImage
* image
= GetLevelImage(target(), 0);
1297 image
->WillModifyTexImage();
1300 void Texture::OnDidModifyPixels() {
1301 gfx::GLImage
* image
= GetLevelImage(target(), 0);
1303 image
->DidModifyTexImage();
1306 void Texture::DumpLevelMemory(base::trace_event::ProcessMemoryDump
* pmd
,
1307 uint64_t client_tracing_id
,
1308 const std::string
& dump_name
) const {
1309 for (uint32_t face_index
= 0; face_index
< face_infos_
.size(); ++face_index
) {
1310 const auto& level_infos
= face_infos_
[face_index
].level_infos
;
1311 for (uint32_t level_index
= 0; level_index
< level_infos
.size();
1313 // Skip levels with no size. Textures will have empty levels for all
1314 // potential mip levels which are not in use.
1315 if (!level_infos
[level_index
].estimated_size
)
1318 if (level_infos
[level_index
].image
) {
1319 // If a level is backed by a GLImage, ask the GLImage to dump itself.
1320 level_infos
[level_index
].image
->OnMemoryDump(
1321 pmd
, client_tracing_id
,
1322 base::StringPrintf("%s/face_%d/level_%d", dump_name
.c_str(),
1323 face_index
, level_index
));
1325 // If a level is not backed by a GLImage, create a simple dump.
1326 base::trace_event::MemoryAllocatorDump
* dump
= pmd
->CreateAllocatorDump(
1327 base::StringPrintf("%s/face_%d/level_%d", dump_name
.c_str(),
1328 face_index
, level_index
));
1330 base::trace_event::MemoryAllocatorDump::kNameSize
,
1331 base::trace_event::MemoryAllocatorDump::kUnitsBytes
,
1332 static_cast<uint64_t>(level_infos
[level_index
].estimated_size
));
1338 TextureRef::TextureRef(TextureManager
* manager
,
1341 : manager_(manager
),
1343 client_id_(client_id
),
1347 texture_
->AddTextureRef(this);
1348 manager_
->StartTracking(this);
1351 scoped_refptr
<TextureRef
> TextureRef::Create(TextureManager
* manager
,
1353 GLuint service_id
) {
1354 return new TextureRef(manager
, client_id
, new Texture(service_id
));
1357 TextureRef::~TextureRef() {
1358 manager_
->StopTracking(this);
1359 texture_
->RemoveTextureRef(this, manager_
->have_context_
);
1363 TextureManager::TextureManager(MemoryTracker
* memory_tracker
,
1364 FeatureInfo
* feature_info
,
1365 GLint max_texture_size
,
1366 GLint max_cube_map_texture_size
,
1367 GLint max_rectangle_texture_size
,
1368 GLint max_3d_texture_size
,
1369 bool use_default_textures
)
1370 : memory_tracker_managed_(
1371 new MemoryTypeTracker(memory_tracker
, MemoryTracker::kManaged
)),
1372 memory_tracker_unmanaged_(
1373 new MemoryTypeTracker(memory_tracker
, MemoryTracker::kUnmanaged
)),
1374 memory_tracker_(memory_tracker
),
1375 feature_info_(feature_info
),
1376 framebuffer_manager_(NULL
),
1377 max_texture_size_(max_texture_size
),
1378 max_cube_map_texture_size_(max_cube_map_texture_size
),
1379 max_rectangle_texture_size_(max_rectangle_texture_size
),
1380 max_3d_texture_size_(max_3d_texture_size
),
1381 max_levels_(ComputeMipMapCount(GL_TEXTURE_2D
,
1385 max_cube_map_levels_(ComputeMipMapCount(GL_TEXTURE_CUBE_MAP
,
1386 max_cube_map_texture_size
,
1387 max_cube_map_texture_size
,
1388 max_cube_map_texture_size
)),
1389 max_3d_levels_(ComputeMipMapCount(GL_TEXTURE_3D
,
1390 // Same as GL_TEXTURE_2D_ARRAY
1391 max_3d_texture_size
,
1392 max_3d_texture_size
,
1393 max_3d_texture_size
)),
1394 use_default_textures_(use_default_textures
),
1395 num_unrenderable_textures_(0),
1396 num_unsafe_textures_(0),
1397 num_uncleared_mips_(0),
1400 have_context_(true) {
1401 for (int ii
= 0; ii
< kNumDefaultTextures
; ++ii
) {
1402 black_texture_ids_
[ii
] = 0;
1406 bool TextureManager::Initialize() {
1407 // TODO(gman): The default textures have to be real textures, not the 0
1408 // texture because we simulate non shared resources on top of shared
1409 // resources and all contexts that share resource share the same default
1411 default_textures_
[kTexture2D
] = CreateDefaultAndBlackTextures(
1412 GL_TEXTURE_2D
, &black_texture_ids_
[kTexture2D
]);
1413 default_textures_
[kCubeMap
] = CreateDefaultAndBlackTextures(
1414 GL_TEXTURE_CUBE_MAP
, &black_texture_ids_
[kCubeMap
]);
1416 if (feature_info_
->feature_flags().oes_egl_image_external
) {
1417 default_textures_
[kExternalOES
] = CreateDefaultAndBlackTextures(
1418 GL_TEXTURE_EXTERNAL_OES
, &black_texture_ids_
[kExternalOES
]);
1421 if (feature_info_
->feature_flags().arb_texture_rectangle
) {
1422 default_textures_
[kRectangleARB
] = CreateDefaultAndBlackTextures(
1423 GL_TEXTURE_RECTANGLE_ARB
, &black_texture_ids_
[kRectangleARB
]);
1426 // When created from InProcessCommandBuffer, we won't have a |memory_tracker_|
1427 // so don't register a dump provider.
1428 if (memory_tracker_
) {
1429 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
1430 this, base::ThreadTaskRunnerHandle::Get());
1436 scoped_refptr
<TextureRef
>
1437 TextureManager::CreateDefaultAndBlackTextures(
1439 GLuint
* black_texture
) {
1440 static uint8 black
[] = {0, 0, 0, 255};
1442 // Sampling a texture not associated with any EGLImage sibling will return
1443 // black values according to the spec.
1444 bool needs_initialization
= (target
!= GL_TEXTURE_EXTERNAL_OES
);
1445 bool needs_faces
= (target
== GL_TEXTURE_CUBE_MAP
);
1447 // Make default textures and texture for replacing non-renderable textures.
1449 const int num_ids
= use_default_textures_
? 2 : 1;
1450 glGenTextures(num_ids
, ids
);
1451 for (int ii
= 0; ii
< num_ids
; ++ii
) {
1452 glBindTexture(target
, ids
[ii
]);
1453 if (needs_initialization
) {
1455 for (int jj
= 0; jj
< GLES2Util::kNumFaces
; ++jj
) {
1456 glTexImage2D(GLES2Util::IndexToGLFaceTarget(jj
), 0, GL_RGBA
, 1, 1, 0,
1457 GL_RGBA
, GL_UNSIGNED_BYTE
, black
);
1460 glTexImage2D(target
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
,
1461 GL_UNSIGNED_BYTE
, black
);
1465 glBindTexture(target
, 0);
1467 scoped_refptr
<TextureRef
> default_texture
;
1468 if (use_default_textures_
) {
1469 default_texture
= TextureRef::Create(this, 0, ids
[1]);
1470 SetTarget(default_texture
.get(), target
);
1472 for (int ii
= 0; ii
< GLES2Util::kNumFaces
; ++ii
) {
1473 SetLevelInfo(default_texture
.get(), GLES2Util::IndexToGLFaceTarget(ii
),
1474 0, GL_RGBA
, 1, 1, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
,
1478 if (needs_initialization
) {
1479 SetLevelInfo(default_texture
.get(), GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 1,
1480 0, GL_RGBA
, GL_UNSIGNED_BYTE
, gfx::Rect(1, 1));
1482 SetLevelInfo(default_texture
.get(), GL_TEXTURE_EXTERNAL_OES
, 0, GL_RGBA
,
1483 1, 1, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, gfx::Rect(1, 1));
1488 *black_texture
= ids
[0];
1489 return default_texture
;
1492 bool TextureManager::ValidForTarget(
1493 GLenum target
, GLint level
, GLsizei width
, GLsizei height
, GLsizei depth
) {
1494 GLsizei max_size
= MaxSizeForTarget(target
) >> level
;
1495 return level
>= 0 &&
1499 level
< MaxLevelsForTarget(target
) &&
1500 width
<= max_size
&&
1501 height
<= max_size
&&
1502 depth
<= max_size
&&
1503 (level
== 0 || feature_info_
->feature_flags().npot_ok
||
1504 (!GLES2Util::IsNPOT(width
) &&
1505 !GLES2Util::IsNPOT(height
) &&
1506 !GLES2Util::IsNPOT(depth
))) &&
1507 (target
!= GL_TEXTURE_CUBE_MAP
|| (width
== height
&& depth
== 1)) &&
1508 (target
!= GL_TEXTURE_2D
|| (depth
== 1));
1511 void TextureManager::SetTarget(TextureRef
* ref
, GLenum target
) {
1514 ->SetTarget(feature_info_
.get(), target
, MaxLevelsForTarget(target
));
1517 void TextureManager::SetLevelClearedRect(TextureRef
* ref
,
1520 const gfx::Rect
& cleared_rect
) {
1522 ref
->texture()->SetLevelClearedRect(target
, level
, cleared_rect
);
1525 void TextureManager::SetLevelCleared(TextureRef
* ref
,
1530 ref
->texture()->SetLevelCleared(target
, level
, cleared
);
1533 bool TextureManager::ClearRenderableLevels(
1534 GLES2Decoder
* decoder
, TextureRef
* ref
) {
1536 return ref
->texture()->ClearRenderableLevels(decoder
);
1539 bool TextureManager::ClearTextureLevel(
1540 GLES2Decoder
* decoder
, TextureRef
* ref
,
1541 GLenum target
, GLint level
) {
1543 Texture
* texture
= ref
->texture();
1544 if (texture
->num_uncleared_mips() == 0) {
1547 bool result
= texture
->ClearLevel(decoder
, target
, level
);
1548 texture
->UpdateCleared();
1552 void TextureManager::SetLevelInfo(TextureRef
* ref
,
1555 GLenum internal_format
,
1562 const gfx::Rect
& cleared_rect
) {
1563 DCHECK(gfx::Rect(width
, height
).Contains(cleared_rect
));
1565 Texture
* texture
= ref
->texture();
1567 texture
->GetMemTracker()->TrackMemFree(texture
->estimated_size());
1568 texture
->SetLevelInfo(feature_info_
.get(), target
, level
, internal_format
,
1569 width
, height
, depth
, border
, format
, type
,
1571 texture
->GetMemTracker()->TrackMemAlloc(texture
->estimated_size());
1574 Texture
* TextureManager::Produce(TextureRef
* ref
) {
1576 return ref
->texture();
1579 TextureRef
* TextureManager::Consume(
1583 scoped_refptr
<TextureRef
> ref(new TextureRef(this, client_id
, texture
));
1584 bool result
= textures_
.insert(std::make_pair(client_id
, ref
)).second
;
1589 void TextureManager::SetParameteri(
1590 const char* function_name
, ErrorState
* error_state
,
1591 TextureRef
* ref
, GLenum pname
, GLint param
) {
1592 DCHECK(error_state
);
1594 Texture
* texture
= ref
->texture();
1595 GLenum result
= texture
->SetParameteri(feature_info_
.get(), pname
, param
);
1596 if (result
!= GL_NO_ERROR
) {
1597 if (result
== GL_INVALID_ENUM
) {
1598 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1599 error_state
, function_name
, param
, "param");
1601 ERRORSTATE_SET_GL_ERROR_INVALID_PARAMI(
1602 error_state
, result
, function_name
, pname
, param
);
1605 // Texture tracking pools exist only for the command decoder, so
1606 // do not pass them on to the native GL implementation.
1607 if (pname
!= GL_TEXTURE_POOL_CHROMIUM
) {
1608 glTexParameteri(texture
->target(), pname
, param
);
1613 void TextureManager::SetParameterf(
1614 const char* function_name
, ErrorState
* error_state
,
1615 TextureRef
* ref
, GLenum pname
, GLfloat param
) {
1616 DCHECK(error_state
);
1618 Texture
* texture
= ref
->texture();
1619 GLenum result
= texture
->SetParameterf(feature_info_
.get(), pname
, param
);
1620 if (result
!= GL_NO_ERROR
) {
1621 if (result
== GL_INVALID_ENUM
) {
1622 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1623 error_state
, function_name
, pname
, "pname");
1625 ERRORSTATE_SET_GL_ERROR_INVALID_PARAMF(
1626 error_state
, result
, function_name
, pname
, param
);
1629 // Texture tracking pools exist only for the command decoder, so
1630 // do not pass them on to the native GL implementation.
1631 if (pname
!= GL_TEXTURE_POOL_CHROMIUM
) {
1632 glTexParameterf(texture
->target(), pname
, param
);
1637 bool TextureManager::MarkMipmapsGenerated(TextureRef
* ref
) {
1639 Texture
* texture
= ref
->texture();
1640 texture
->GetMemTracker()->TrackMemFree(texture
->estimated_size());
1641 bool result
= texture
->MarkMipmapsGenerated(feature_info_
.get());
1642 texture
->GetMemTracker()->TrackMemAlloc(texture
->estimated_size());
1646 TextureRef
* TextureManager::CreateTexture(
1647 GLuint client_id
, GLuint service_id
) {
1648 DCHECK_NE(0u, service_id
);
1649 scoped_refptr
<TextureRef
> ref(TextureRef::Create(
1650 this, client_id
, service_id
));
1651 std::pair
<TextureMap::iterator
, bool> result
=
1652 textures_
.insert(std::make_pair(client_id
, ref
));
1653 DCHECK(result
.second
);
1657 TextureRef
* TextureManager::GetTexture(
1658 GLuint client_id
) const {
1659 TextureMap::const_iterator it
= textures_
.find(client_id
);
1660 return it
!= textures_
.end() ? it
->second
.get() : NULL
;
1663 void TextureManager::RemoveTexture(GLuint client_id
) {
1664 TextureMap::iterator it
= textures_
.find(client_id
);
1665 if (it
!= textures_
.end()) {
1666 it
->second
->reset_client_id();
1667 textures_
.erase(it
);
1671 void TextureManager::StartTracking(TextureRef
* ref
) {
1672 Texture
* texture
= ref
->texture();
1674 num_uncleared_mips_
+= texture
->num_uncleared_mips();
1675 if (!texture
->SafeToRenderFrom())
1676 ++num_unsafe_textures_
;
1677 if (!texture
->CanRender(feature_info_
.get()))
1678 ++num_unrenderable_textures_
;
1679 if (texture
->HasImages())
1683 void TextureManager::StopTracking(TextureRef
* ref
) {
1684 if (ref
->num_observers()) {
1685 for (unsigned int i
= 0; i
< destruction_observers_
.size(); i
++) {
1686 destruction_observers_
[i
]->OnTextureRefDestroying(ref
);
1688 DCHECK_EQ(ref
->num_observers(), 0);
1691 Texture
* texture
= ref
->texture();
1694 if (texture
->HasImages()) {
1695 DCHECK_NE(0, num_images_
);
1698 if (!texture
->CanRender(feature_info_
.get())) {
1699 DCHECK_NE(0, num_unrenderable_textures_
);
1700 --num_unrenderable_textures_
;
1702 if (!texture
->SafeToRenderFrom()) {
1703 DCHECK_NE(0, num_unsafe_textures_
);
1704 --num_unsafe_textures_
;
1706 num_uncleared_mips_
-= texture
->num_uncleared_mips();
1707 DCHECK_GE(num_uncleared_mips_
, 0);
1710 MemoryTypeTracker
* TextureManager::GetMemTracker(GLenum tracking_pool
) {
1711 switch (tracking_pool
) {
1712 case GL_TEXTURE_POOL_MANAGED_CHROMIUM
:
1713 return memory_tracker_managed_
.get();
1715 case GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
:
1716 return memory_tracker_unmanaged_
.get();
1725 Texture
* TextureManager::GetTextureForServiceId(GLuint service_id
) const {
1726 // This doesn't need to be fast. It's only used during slow queries.
1727 for (TextureMap::const_iterator it
= textures_
.begin();
1728 it
!= textures_
.end(); ++it
) {
1729 Texture
* texture
= it
->second
->texture();
1730 if (texture
->service_id() == service_id
)
1736 GLsizei
TextureManager::ComputeMipMapCount(GLenum target
,
1741 case GL_TEXTURE_EXTERNAL_OES
:
1745 base::bits::Log2Floor(std::max(std::max(width
, height
), depth
));
1749 void TextureManager::SetLevelImage(
1753 gfx::GLImage
* image
) {
1755 ref
->texture()->SetLevelImage(feature_info_
.get(), target
, level
, image
);
1758 size_t TextureManager::GetSignatureSize() const {
1759 return sizeof(TextureTag
) + sizeof(TextureSignature
);
1762 void TextureManager::AddToSignature(
1766 std::string
* signature
) const {
1767 ref
->texture()->AddToSignature(feature_info_
.get(), target
, level
, signature
);
1770 void TextureManager::UpdateSafeToRenderFrom(int delta
) {
1771 num_unsafe_textures_
+= delta
;
1772 DCHECK_GE(num_unsafe_textures_
, 0);
1775 void TextureManager::UpdateUnclearedMips(int delta
) {
1776 num_uncleared_mips_
+= delta
;
1777 DCHECK_GE(num_uncleared_mips_
, 0);
1780 void TextureManager::UpdateCanRenderCondition(
1781 Texture::CanRenderCondition old_condition
,
1782 Texture::CanRenderCondition new_condition
) {
1783 if (old_condition
== Texture::CAN_RENDER_NEVER
||
1784 (old_condition
== Texture::CAN_RENDER_ONLY_IF_NPOT
&&
1785 !feature_info_
->feature_flags().npot_ok
)) {
1786 DCHECK_GT(num_unrenderable_textures_
, 0);
1787 --num_unrenderable_textures_
;
1789 if (new_condition
== Texture::CAN_RENDER_NEVER
||
1790 (new_condition
== Texture::CAN_RENDER_ONLY_IF_NPOT
&&
1791 !feature_info_
->feature_flags().npot_ok
))
1792 ++num_unrenderable_textures_
;
1795 void TextureManager::UpdateNumImages(int delta
) {
1796 num_images_
+= delta
;
1797 DCHECK_GE(num_images_
, 0);
1800 void TextureManager::IncFramebufferStateChangeCount() {
1801 if (framebuffer_manager_
)
1802 framebuffer_manager_
->IncFramebufferStateChangeCount();
1805 bool TextureManager::ValidateFormatAndTypeCombination(
1806 ErrorState
* error_state
, const char* function_name
, GLenum format
,
1808 // TODO(zmo): now this is only called by GLES2DecoderImpl::DoCopyTexImage2D
1809 // and is incorrect for ES3. Fix this.
1810 if (!g_format_type_validator
.Get().IsValid(format
, format
, type
)) {
1811 ERRORSTATE_SET_GL_ERROR(
1812 error_state
, GL_INVALID_OPERATION
, function_name
,
1813 (std::string("invalid type ") +
1814 GLES2Util::GetStringEnum(type
) + " for format " +
1815 GLES2Util::GetStringEnum(format
)).c_str());
1821 bool TextureManager::ValidateTextureParameters(
1822 ErrorState
* error_state
, const char* function_name
,
1823 GLenum format
, GLenum type
, GLenum internal_format
, GLint level
) {
1824 const Validators
* validators
= feature_info_
->validators();
1825 if (!validators
->texture_format
.IsValid(format
)) {
1826 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1827 error_state
, function_name
, format
, "format");
1830 if (!validators
->pixel_type
.IsValid(type
)) {
1831 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1832 error_state
, function_name
, type
, "type");
1835 if (!g_format_type_validator
.Get().IsValid(internal_format
, format
, type
)) {
1836 ERRORSTATE_SET_GL_ERROR(
1837 error_state
, GL_INVALID_OPERATION
, function_name
,
1838 "invalid internalformat/format/type combination");
1841 // For TexSubImage calls, internal_format isn't part of the parameters,
1842 // so its validation needs to be after the internal_format/format/type
1843 // combination validation. Otherwise, an unexpected INVALID_ENUM could be
1844 // generated instead of INVALID_OPERATION.
1845 if (!validators
->texture_internal_format
.IsValid(internal_format
)) {
1846 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1847 error_state
, function_name
, internal_format
, "internal_format");
1850 if (!feature_info_
->IsES3Enabled()) {
1851 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
1852 if ((channels
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0 && level
) {
1853 ERRORSTATE_SET_GL_ERROR(
1854 error_state
, GL_INVALID_OPERATION
, function_name
,
1855 (std::string("invalid format ") + GLES2Util::GetStringEnum(format
) +
1856 " for level != 0").c_str());
1863 // Gets the texture id for a given target.
1864 TextureRef
* TextureManager::GetTextureInfoForTarget(
1865 ContextState
* state
, GLenum target
) {
1866 TextureUnit
& unit
= state
->texture_units
[state
->active_texture_unit
];
1867 TextureRef
* texture
= NULL
;
1870 texture
= unit
.bound_texture_2d
.get();
1872 case GL_TEXTURE_CUBE_MAP
:
1873 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
1874 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
1875 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
1876 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
1877 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
1878 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
1879 texture
= unit
.bound_texture_cube_map
.get();
1881 case GL_TEXTURE_EXTERNAL_OES
:
1882 texture
= unit
.bound_texture_external_oes
.get();
1884 case GL_TEXTURE_RECTANGLE_ARB
:
1885 texture
= unit
.bound_texture_rectangle_arb
.get();
1888 texture
= unit
.bound_texture_3d
.get();
1890 case GL_TEXTURE_2D_ARRAY
:
1891 texture
= unit
.bound_texture_2d_array
.get();
1900 TextureRef
* TextureManager::GetTextureInfoForTargetUnlessDefault(
1901 ContextState
* state
, GLenum target
) {
1902 TextureRef
* texture
= GetTextureInfoForTarget(state
, target
);
1905 if (texture
== GetDefaultTextureInfo(target
))
1910 bool TextureManager::ValidateTexImage(
1911 ContextState
* state
,
1912 const char* function_name
,
1913 const DoTexImageArguments
& args
,
1914 TextureRef
** texture_ref
) {
1915 ErrorState
* error_state
= state
->GetErrorState();
1916 const Validators
* validators
= feature_info_
->validators();
1917 if (((args
.command_type
== DoTexImageArguments::kTexImage2D
) &&
1918 !validators
->texture_target
.IsValid(args
.target
)) ||
1919 ((args
.command_type
== DoTexImageArguments::kTexImage3D
) &&
1920 !validators
->texture_3_d_target
.IsValid(args
.target
))) {
1921 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1922 error_state
, function_name
, args
.target
, "target");
1925 if (!ValidateTextureParameters(
1926 error_state
, function_name
, args
.format
, args
.type
,
1927 args
.internal_format
, args
.level
)) {
1930 if (!ValidForTarget(args
.target
, args
.level
,
1931 args
.width
, args
.height
, args
.depth
) ||
1933 ERRORSTATE_SET_GL_ERROR(
1934 error_state
, GL_INVALID_VALUE
, function_name
,
1935 "dimensions out of range");
1938 if ((GLES2Util::GetChannelsForFormat(args
.format
) &
1939 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0 && args
.pixels
1940 && !feature_info_
->IsES3Enabled()) {
1941 ERRORSTATE_SET_GL_ERROR(
1942 error_state
, GL_INVALID_OPERATION
,
1943 function_name
, "can not supply data for depth or stencil textures");
1947 TextureRef
* local_texture_ref
= GetTextureInfoForTarget(state
, args
.target
);
1948 if (!local_texture_ref
) {
1949 ERRORSTATE_SET_GL_ERROR(
1950 error_state
, GL_INVALID_OPERATION
, function_name
,
1951 "unknown texture for target");
1954 if (local_texture_ref
->texture()->IsImmutable()) {
1955 ERRORSTATE_SET_GL_ERROR(
1956 error_state
, GL_INVALID_OPERATION
, function_name
,
1957 "texture is immutable");
1961 if (!memory_tracker_managed_
->EnsureGPUMemoryAvailable(args
.pixels_size
)) {
1962 ERRORSTATE_SET_GL_ERROR(error_state
, GL_OUT_OF_MEMORY
, function_name
,
1967 // Write the TextureReference since this is valid.
1968 *texture_ref
= local_texture_ref
;
1972 void TextureManager::ValidateAndDoTexImage(
1973 DecoderTextureState
* texture_state
,
1974 ContextState
* state
,
1975 DecoderFramebufferState
* framebuffer_state
,
1976 const char* function_name
,
1977 const DoTexImageArguments
& args
) {
1978 TextureRef
* texture_ref
;
1979 if (!ValidateTexImage(state
, function_name
, args
, &texture_ref
)) {
1983 // ValidateTexImage is passed already.
1984 Texture
* texture
= texture_ref
->texture();
1985 bool need_cube_map_workaround
=
1986 texture
->target() == GL_TEXTURE_CUBE_MAP
&&
1987 (texture_state
->force_cube_complete
||
1988 (texture_state
->force_cube_map_positive_x_allocation
&&
1989 args
.target
!= GL_TEXTURE_CUBE_MAP_POSITIVE_X
));
1990 if (need_cube_map_workaround
) {
1991 std::vector
<GLenum
> undefined_faces
;
1992 if (texture_state
->force_cube_complete
) {
1995 for (unsigned i
= 0; i
< 6; i
++) {
1997 texture
->GetLevelSize(GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
,
1998 args
.level
, &width
, &height
, nullptr);
1999 if (!defined
|| GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
== args
.target
)
2000 undefined_faces
.push_back(GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
);
2002 } else if (texture_state
->force_cube_map_positive_x_allocation
&&
2003 args
.target
!= GL_TEXTURE_CUBE_MAP_POSITIVE_X
) {
2006 if (!texture
->GetLevelSize(GL_TEXTURE_CUBE_MAP_POSITIVE_X
, args
.level
,
2007 &width
, &height
, nullptr)) {
2008 undefined_faces
.push_back(GL_TEXTURE_CUBE_MAP_POSITIVE_X
);
2010 undefined_faces
.push_back(args
.target
);
2013 DCHECK(undefined_faces
.size());
2014 if (!memory_tracker_managed_
->EnsureGPUMemoryAvailable(
2015 undefined_faces
.size() * args
.pixels_size
)) {
2016 ERRORSTATE_SET_GL_ERROR(state
->GetErrorState(), GL_OUT_OF_MEMORY
,
2017 function_name
, "out of memory");
2020 DoTexImageArguments new_args
= args
;
2021 scoped_ptr
<char[]> zero(new char[args
.pixels_size
]);
2022 memset(zero
.get(), 0, args
.pixels_size
);
2023 for (GLenum face
: undefined_faces
) {
2024 new_args
.target
= face
;
2025 if (face
== args
.target
) {
2026 new_args
.pixels
= args
.pixels
;
2028 new_args
.pixels
= zero
.get();
2030 DoTexImage(texture_state
, state
->GetErrorState(), framebuffer_state
,
2031 function_name
, texture_ref
, new_args
);
2036 DoTexImage(texture_state
, state
->GetErrorState(), framebuffer_state
,
2037 function_name
, texture_ref
, args
);
2040 GLenum
TextureManager::AdjustTexFormat(GLenum format
) const {
2041 // TODO(bajones): GLES 3 allows for internal format and format to differ.
2042 // This logic may need to change as a result.
2043 if (gfx::GetGLImplementation() == gfx::kGLImplementationDesktopGL
) {
2044 if (format
== GL_SRGB_EXT
)
2046 if (format
== GL_SRGB_ALPHA_EXT
)
2052 void TextureManager::DoTexImage(
2053 DecoderTextureState
* texture_state
,
2054 ErrorState
* error_state
,
2055 DecoderFramebufferState
* framebuffer_state
,
2056 const char* function_name
,
2057 TextureRef
* texture_ref
,
2058 const DoTexImageArguments
& args
) {
2059 Texture
* texture
= texture_ref
->texture();
2060 GLsizei tex_width
= 0;
2061 GLsizei tex_height
= 0;
2062 GLsizei tex_depth
= 0;
2063 GLenum tex_type
= 0;
2064 GLenum tex_format
= 0;
2065 bool level_is_same
=
2066 texture
->GetLevelSize(
2067 args
.target
, args
.level
, &tex_width
, &tex_height
, &tex_depth
) &&
2068 texture
->GetLevelType(args
.target
, args
.level
, &tex_type
, &tex_format
) &&
2069 args
.width
== tex_width
&& args
.height
== tex_height
&&
2070 args
.depth
== tex_depth
&& args
.type
== tex_type
&&
2071 args
.format
== tex_format
;
2073 if (level_is_same
&& !args
.pixels
) {
2074 // Just set the level texture but mark the texture as uncleared.
2075 SetLevelInfo(texture_ref
, args
.target
, args
.level
, args
.internal_format
,
2076 args
.width
, args
.height
, args
.depth
, args
.border
, args
.format
,
2077 args
.type
, gfx::Rect());
2078 texture_state
->tex_image_failed
= false;
2082 if (texture
->IsAttachedToFramebuffer()) {
2083 framebuffer_state
->clear_state_dirty
= true;
2086 if (texture_state
->texsubimage_faster_than_teximage
&&
2087 level_is_same
&& args
.pixels
) {
2089 ScopedTextureUploadTimer
timer(texture_state
);
2090 if (args
.command_type
== DoTexImageArguments::kTexImage3D
) {
2091 glTexSubImage3D(args
.target
, args
.level
, 0, 0, 0,
2092 args
.width
, args
.height
, args
.depth
,
2093 args
.format
, args
.type
, args
.pixels
);
2095 glTexSubImage2D(args
.target
, args
.level
, 0, 0, args
.width
, args
.height
,
2096 AdjustTexFormat(args
.format
), args
.type
, args
.pixels
);
2099 SetLevelCleared(texture_ref
, args
.target
, args
.level
, true);
2100 texture_state
->tex_image_failed
= false;
2104 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state
, function_name
);
2106 ScopedTextureUploadTimer
timer(texture_state
);
2107 if (args
.command_type
== DoTexImageArguments::kTexImage3D
) {
2108 glTexImage3D(args
.target
, args
.level
, args
.internal_format
, args
.width
,
2109 args
.height
, args
.depth
, args
.border
, args
.format
,
2110 args
.type
, args
.pixels
);
2112 glTexImage2D(args
.target
, args
.level
, args
.internal_format
, args
.width
,
2113 args
.height
, args
.border
, AdjustTexFormat(args
.format
),
2114 args
.type
, args
.pixels
);
2117 GLenum error
= ERRORSTATE_PEEK_GL_ERROR(error_state
, function_name
);
2118 if (error
== GL_NO_ERROR
) {
2120 texture_ref
, args
.target
, args
.level
, args
.internal_format
, args
.width
,
2121 args
.height
, args
.depth
, args
.border
, args
.format
, args
.type
,
2122 args
.pixels
!= NULL
? gfx::Rect(args
.width
, args
.height
) : gfx::Rect());
2123 texture_state
->tex_image_failed
= false;
2127 ScopedTextureUploadTimer::ScopedTextureUploadTimer(
2128 DecoderTextureState
* texture_state
)
2129 : texture_state_(texture_state
),
2130 begin_time_(base::TimeTicks::Now()) {
2133 ScopedTextureUploadTimer::~ScopedTextureUploadTimer() {
2134 texture_state_
->texture_upload_count
++;
2135 texture_state_
->total_texture_upload_time
+=
2136 base::TimeTicks::Now() - begin_time_
;
2139 bool TextureManager::OnMemoryDump(const base::trace_event::MemoryDumpArgs
& args
,
2140 base::trace_event::ProcessMemoryDump
* pmd
) {
2141 for (const auto& resource
: textures_
) {
2142 // Only dump memory info for textures actually owned by this TextureManager.
2143 DumpTextureRef(pmd
, resource
.second
.get());
2146 // Also dump TextureManager internal textures, if allocated.
2147 for (int i
= 0; i
< kNumDefaultTextures
; i
++) {
2148 if (default_textures_
[i
]) {
2149 DumpTextureRef(pmd
, default_textures_
[i
].get());
2156 void TextureManager::DumpTextureRef(base::trace_event::ProcessMemoryDump
* pmd
,
2158 uint32_t size
= ref
->texture()->estimated_size();
2160 // Ignore unallocated texture IDs.
2164 std::string dump_name
=
2165 base::StringPrintf("gpu/gl/textures/client_%d/texture_%d",
2166 memory_tracker_
->ClientId(), ref
->client_id());
2168 base::trace_event::MemoryAllocatorDump
* dump
=
2169 pmd
->CreateAllocatorDump(dump_name
);
2170 dump
->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize
,
2171 base::trace_event::MemoryAllocatorDump::kUnitsBytes
,
2172 static_cast<uint64_t>(size
));
2174 // Add the |client_guid| which expresses shared ownership with the client
2176 auto client_guid
= gfx::GetGLTextureGUIDForTracing(
2177 memory_tracker_
->ClientTracingId(), ref
->client_id());
2178 pmd
->CreateSharedGlobalAllocatorDump(client_guid
);
2179 pmd
->AddOwnershipEdge(dump
->guid(), client_guid
);
2181 // Add a |service_guid| which expresses shared ownership between the various
2183 // TODO(ericrk): May need to ensure uniqueness using GLShareGroup and
2184 // potentially cross-share-group sharing via EGLImages. crbug.com/512534
2186 gfx::GetGLTextureGUIDForTracing(0, ref
->texture()->service_id());
2187 pmd
->CreateSharedGlobalAllocatorDump(service_guid
);
2189 int importance
= 0; // Default importance.
2190 // The link to the memory tracking |client_id| is given a higher importance
2192 if (ref
== ref
->texture()->memory_tracking_ref_
)
2195 pmd
->AddOwnershipEdge(client_guid
, service_guid
, importance
);
2197 // Dump all sub-levels held by the texture. They will appear below the main
2198 // gl/textures/client_X/texture_Y dump.
2199 ref
->texture()->DumpLevelMemory(pmd
, memory_tracker_
->ClientTracingId(),
2203 } // namespace gles2