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(
865 GLsizei depth
) const {
866 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
867 if (level
>= 0 && face_index
< face_infos_
.size() &&
868 static_cast<size_t>(level
) < face_infos_
[face_index
].level_infos
.size()) {
869 const LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
873 return SafeAddInt32(xoffset
, width
, &max_x
) &&
874 SafeAddInt32(yoffset
, height
, &max_y
) &&
875 SafeAddInt32(zoffset
, depth
, &max_z
) &&
879 max_x
<= info
.width
&&
880 max_y
<= info
.height
&&
886 bool Texture::GetLevelSize(
887 GLint target
, GLint level
,
888 GLsizei
* width
, GLsizei
* height
, GLsizei
* depth
) const {
891 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
892 if (level
>= 0 && face_index
< face_infos_
.size() &&
893 static_cast<size_t>(level
) < face_infos_
[face_index
].level_infos
.size()) {
894 const LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
895 if (info
.target
!= 0) {
897 *height
= info
.height
;
906 bool Texture::GetLevelType(
907 GLint target
, GLint level
, GLenum
* type
, GLenum
* internal_format
) const {
909 DCHECK(internal_format
);
910 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
911 if (level
>= 0 && face_index
< face_infos_
.size() &&
912 static_cast<size_t>(level
) < face_infos_
[face_index
].level_infos
.size()) {
913 const LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
914 if (info
.target
!= 0) {
916 *internal_format
= info
.internal_format
;
923 GLenum
Texture::SetParameteri(
924 const FeatureInfo
* feature_info
, GLenum pname
, GLint param
) {
925 DCHECK(feature_info
);
927 if (target_
== GL_TEXTURE_EXTERNAL_OES
||
928 target_
== GL_TEXTURE_RECTANGLE_ARB
) {
929 if (pname
== GL_TEXTURE_MIN_FILTER
&&
930 (param
!= GL_NEAREST
&& param
!= GL_LINEAR
))
931 return GL_INVALID_ENUM
;
932 if ((pname
== GL_TEXTURE_WRAP_S
|| pname
== GL_TEXTURE_WRAP_T
) &&
933 param
!= GL_CLAMP_TO_EDGE
)
934 return GL_INVALID_ENUM
;
938 case GL_TEXTURE_MIN_LOD
:
939 case GL_TEXTURE_MAX_LOD
:
941 GLfloat fparam
= static_cast<GLfloat
>(param
);
942 return SetParameterf(feature_info
, pname
, fparam
);
944 case GL_TEXTURE_MIN_FILTER
:
945 if (!feature_info
->validators()->texture_min_filter_mode
.IsValid(param
)) {
946 return GL_INVALID_ENUM
;
950 case GL_TEXTURE_MAG_FILTER
:
951 if (!feature_info
->validators()->texture_mag_filter_mode
.IsValid(param
)) {
952 return GL_INVALID_ENUM
;
956 case GL_TEXTURE_POOL_CHROMIUM
:
957 if (!feature_info
->validators()->texture_pool
.IsValid(param
)) {
958 return GL_INVALID_ENUM
;
960 GetMemTracker()->TrackMemFree(estimated_size());
962 GetMemTracker()->TrackMemAlloc(estimated_size());
964 case GL_TEXTURE_WRAP_R
:
965 if (!feature_info
->validators()->texture_wrap_mode
.IsValid(param
)) {
966 return GL_INVALID_ENUM
;
970 case GL_TEXTURE_WRAP_S
:
971 if (!feature_info
->validators()->texture_wrap_mode
.IsValid(param
)) {
972 return GL_INVALID_ENUM
;
976 case GL_TEXTURE_WRAP_T
:
977 if (!feature_info
->validators()->texture_wrap_mode
.IsValid(param
)) {
978 return GL_INVALID_ENUM
;
982 case GL_TEXTURE_COMPARE_FUNC
:
983 if (!feature_info
->validators()->texture_compare_func
.IsValid(param
)) {
984 return GL_INVALID_ENUM
;
986 compare_func_
= param
;
988 case GL_TEXTURE_COMPARE_MODE
:
989 if (!feature_info
->validators()->texture_compare_mode
.IsValid(param
)) {
990 return GL_INVALID_ENUM
;
992 compare_mode_
= param
;
994 case GL_TEXTURE_BASE_LEVEL
:
996 return GL_INVALID_VALUE
;
1000 case GL_TEXTURE_MAX_LEVEL
:
1002 return GL_INVALID_VALUE
;
1006 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
1008 return GL_INVALID_VALUE
;
1011 case GL_TEXTURE_USAGE_ANGLE
:
1012 if (!feature_info
->validators()->texture_usage
.IsValid(param
)) {
1013 return GL_INVALID_ENUM
;
1019 return GL_INVALID_ENUM
;
1021 Update(feature_info
);
1023 UpdateCanRenderCondition();
1027 GLenum
Texture::SetParameterf(
1028 const FeatureInfo
* feature_info
, GLenum pname
, GLfloat param
) {
1030 case GL_TEXTURE_MIN_FILTER
:
1031 case GL_TEXTURE_MAG_FILTER
:
1032 case GL_TEXTURE_POOL_CHROMIUM
:
1033 case GL_TEXTURE_WRAP_R
:
1034 case GL_TEXTURE_WRAP_S
:
1035 case GL_TEXTURE_WRAP_T
:
1036 case GL_TEXTURE_COMPARE_FUNC
:
1037 case GL_TEXTURE_COMPARE_MODE
:
1038 case GL_TEXTURE_BASE_LEVEL
:
1039 case GL_TEXTURE_MAX_LEVEL
:
1040 case GL_TEXTURE_USAGE_ANGLE
:
1042 GLint iparam
= static_cast<GLint
>(param
);
1043 return SetParameteri(feature_info
, pname
, iparam
);
1045 case GL_TEXTURE_MIN_LOD
:
1048 case GL_TEXTURE_MAX_LOD
:
1051 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
1053 return GL_INVALID_VALUE
;
1058 return GL_INVALID_ENUM
;
1063 void Texture::Update(const FeatureInfo
* feature_info
) {
1064 // Update npot status.
1065 // Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others
1066 npot_
= (target_
== GL_TEXTURE_EXTERNAL_OES
) || (num_npot_faces_
> 0);
1068 if (face_infos_
.empty()) {
1069 texture_complete_
= false;
1070 cube_complete_
= false;
1074 // Update texture_complete and cube_complete status.
1075 const Texture::FaceInfo
& first_face
= face_infos_
[0];
1076 const Texture::LevelInfo
& first_level
= first_face
.level_infos
[0];
1077 const GLsizei levels_needed
= first_face
.num_mip_levels
;
1080 max_level_set_
>= (levels_needed
- 1) && max_level_set_
>= 0;
1081 cube_complete_
= (face_infos_
.size() == 6) &&
1082 (first_level
.width
== first_level
.height
);
1084 if (first_level
.width
== 0 || first_level
.height
== 0) {
1085 texture_complete_
= false;
1086 } else if (first_level
.type
== GL_FLOAT
&&
1087 !feature_info
->feature_flags().enable_texture_float_linear
&&
1088 (min_filter_
!= GL_NEAREST_MIPMAP_NEAREST
||
1089 mag_filter_
!= GL_NEAREST
)) {
1090 texture_complete_
= false;
1091 } else if (first_level
.type
== GL_HALF_FLOAT_OES
&&
1092 !feature_info
->feature_flags().enable_texture_half_float_linear
&&
1093 (min_filter_
!= GL_NEAREST_MIPMAP_NEAREST
||
1094 mag_filter_
!= GL_NEAREST
)) {
1095 texture_complete_
= false;
1098 if (cube_complete_
&& texture_level0_dirty_
) {
1099 texture_level0_complete_
= true;
1100 for (size_t ii
= 0; ii
< face_infos_
.size(); ++ii
) {
1101 const Texture::LevelInfo
& level0
= face_infos_
[ii
].level_infos
[0];
1102 if (!TextureFaceComplete(first_level
,
1105 level0
.internal_format
,
1111 texture_level0_complete_
= false;
1115 texture_level0_dirty_
= false;
1117 cube_complete_
&= texture_level0_complete_
;
1119 if (texture_complete_
&& texture_mips_dirty_
) {
1120 texture_mips_complete_
= true;
1122 ii
< face_infos_
.size() && texture_mips_complete_
;
1124 const Texture::FaceInfo
& face_info
= face_infos_
[ii
];
1125 const Texture::LevelInfo
& level0
= face_info
.level_infos
[0];
1126 for (GLsizei jj
= 1; jj
< levels_needed
; ++jj
) {
1127 const Texture::LevelInfo
& level_info
= face_infos_
[ii
].level_infos
[jj
];
1128 if (!TextureMipComplete(level0
,
1131 level_info
.internal_format
,
1137 texture_mips_complete_
= false;
1142 texture_mips_dirty_
= false;
1144 texture_complete_
&= texture_mips_complete_
;
1147 bool Texture::ClearRenderableLevels(GLES2Decoder
* decoder
) {
1153 for (size_t ii
= 0; ii
< face_infos_
.size(); ++ii
) {
1154 const Texture::FaceInfo
& face_info
= face_infos_
[ii
];
1155 for (GLint jj
= 0; jj
< face_info
.num_mip_levels
; ++jj
) {
1156 const Texture::LevelInfo
& info
= face_info
.level_infos
[jj
];
1157 if (info
.target
!= 0) {
1158 if (!ClearLevel(decoder
, info
.target
, jj
)) {
1164 UpdateSafeToRenderFrom(true);
1168 gfx::Rect
Texture::GetLevelClearedRect(GLenum target
, GLint level
) const {
1169 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
1170 if (face_index
>= face_infos_
.size() ||
1171 level
>= static_cast<GLint
>(face_infos_
[face_index
].level_infos
.size())) {
1175 const Texture::LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
1177 return info
.cleared_rect
;
1180 bool Texture::IsLevelCleared(GLenum target
, GLint level
) const {
1181 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
1182 if (face_index
>= face_infos_
.size() ||
1183 level
>= static_cast<GLint
>(face_infos_
[face_index
].level_infos
.size())) {
1187 const Texture::LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
1189 return info
.cleared_rect
== gfx::Rect(info
.width
, info
.height
);
1192 void Texture::InitTextureMaxAnisotropyIfNeeded(GLenum target
) {
1193 if (texture_max_anisotropy_initialized_
)
1195 texture_max_anisotropy_initialized_
= true;
1196 GLfloat params
[] = { 1.0f
};
1197 glTexParameterfv(target
, GL_TEXTURE_MAX_ANISOTROPY_EXT
, params
);
1200 bool Texture::ClearLevel(
1201 GLES2Decoder
* decoder
, GLenum target
, GLint level
) {
1203 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
1204 if (face_index
>= face_infos_
.size() ||
1205 level
>= static_cast<GLint
>(face_infos_
[face_index
].level_infos
.size())) {
1209 Texture::LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
1211 DCHECK(target
== info
.target
);
1213 if (info
.target
== 0 ||
1214 info
.cleared_rect
== gfx::Rect(info
.width
, info
.height
) ||
1215 info
.width
== 0 || info
.height
== 0 || info
.depth
== 0) {
1219 // Clear all remaining sub regions.
1221 0, info
.cleared_rect
.x(), info
.cleared_rect
.right(), info
.width
};
1223 0, info
.cleared_rect
.y(), info
.cleared_rect
.bottom(), info
.height
};
1225 for (size_t j
= 0; j
< 3; ++j
) {
1226 for (size_t i
= 0; i
< 3; ++i
) {
1227 // Center of nine patch is already cleared.
1228 if (j
== 1 && i
== 1)
1231 gfx::Rect
rect(x
[i
], y
[j
], x
[i
+ 1] - x
[i
], y
[j
+ 1] - y
[j
]);
1235 // NOTE: It seems kind of gross to call back into the decoder for this
1236 // but only the decoder knows all the state (like unpack_alignment_)
1237 // that's needed to be able to call GL correctly.
1238 bool cleared
= decoder
->ClearLevel(this, info
.target
, info
.level
,
1239 info
.format
, info
.type
, rect
.x(),
1240 rect
.y(), rect
.width(), rect
.height());
1246 UpdateMipCleared(&info
, info
.width
, info
.height
,
1247 gfx::Rect(info
.width
, info
.height
));
1251 void Texture::SetLevelImage(
1252 const FeatureInfo
* feature_info
,
1255 gfx::GLImage
* image
) {
1256 DCHECK_GE(level
, 0);
1257 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
1258 DCHECK_LT(static_cast<size_t>(face_index
),
1259 face_infos_
.size());
1260 DCHECK_LT(static_cast<size_t>(level
),
1261 face_infos_
[face_index
].level_infos
.size());
1262 Texture::LevelInfo
& info
=
1263 face_infos_
[face_index
].level_infos
[level
];
1264 DCHECK_EQ(info
.target
, target
);
1265 DCHECK_EQ(info
.level
, level
);
1267 UpdateCanRenderCondition();
1270 // TODO(ericrk): Images may have complex sizing not accounted for by
1271 // |estimated_size_|, we should add logic here to update |estimated_size_|
1272 // based on the new GLImage. crbug.com/526298
1275 gfx::GLImage
* Texture::GetLevelImage(GLint target
, GLint level
) const {
1276 if (target
!= GL_TEXTURE_2D
&& target
!= GL_TEXTURE_EXTERNAL_OES
&&
1277 target
!= GL_TEXTURE_RECTANGLE_ARB
) {
1281 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
1282 if (level
>= 0 && face_index
< face_infos_
.size() &&
1283 static_cast<size_t>(level
) < face_infos_
[face_index
].level_infos
.size()) {
1284 const LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
1285 if (info
.target
!= 0) {
1286 return info
.image
.get();
1292 void Texture::OnWillModifyPixels() {
1293 gfx::GLImage
* image
= GetLevelImage(target(), 0);
1295 image
->WillModifyTexImage();
1298 void Texture::OnDidModifyPixels() {
1299 gfx::GLImage
* image
= GetLevelImage(target(), 0);
1301 image
->DidModifyTexImage();
1304 void Texture::DumpLevelMemory(base::trace_event::ProcessMemoryDump
* pmd
,
1305 uint64_t client_tracing_id
,
1306 const std::string
& dump_name
) const {
1307 for (uint32_t face_index
= 0; face_index
< face_infos_
.size(); ++face_index
) {
1308 const auto& level_infos
= face_infos_
[face_index
].level_infos
;
1309 for (uint32_t level_index
= 0; level_index
< level_infos
.size();
1311 // Skip levels with no size. Textures will have empty levels for all
1312 // potential mip levels which are not in use.
1313 if (!level_infos
[level_index
].estimated_size
)
1316 if (level_infos
[level_index
].image
) {
1317 // If a level is backed by a GLImage, ask the GLImage to dump itself.
1318 level_infos
[level_index
].image
->OnMemoryDump(
1319 pmd
, client_tracing_id
,
1320 base::StringPrintf("%s/face_%d/level_%d", dump_name
.c_str(),
1321 face_index
, level_index
));
1323 // If a level is not backed by a GLImage, create a simple dump.
1324 base::trace_event::MemoryAllocatorDump
* dump
= pmd
->CreateAllocatorDump(
1325 base::StringPrintf("%s/face_%d/level_%d", dump_name
.c_str(),
1326 face_index
, level_index
));
1328 base::trace_event::MemoryAllocatorDump::kNameSize
,
1329 base::trace_event::MemoryAllocatorDump::kUnitsBytes
,
1330 static_cast<uint64_t>(level_infos
[level_index
].estimated_size
));
1336 TextureRef::TextureRef(TextureManager
* manager
,
1339 : manager_(manager
),
1341 client_id_(client_id
),
1345 texture_
->AddTextureRef(this);
1346 manager_
->StartTracking(this);
1349 scoped_refptr
<TextureRef
> TextureRef::Create(TextureManager
* manager
,
1351 GLuint service_id
) {
1352 return new TextureRef(manager
, client_id
, new Texture(service_id
));
1355 TextureRef::~TextureRef() {
1356 manager_
->StopTracking(this);
1357 texture_
->RemoveTextureRef(this, manager_
->have_context_
);
1361 TextureManager::TextureManager(MemoryTracker
* memory_tracker
,
1362 FeatureInfo
* feature_info
,
1363 GLint max_texture_size
,
1364 GLint max_cube_map_texture_size
,
1365 GLint max_rectangle_texture_size
,
1366 GLint max_3d_texture_size
,
1367 bool use_default_textures
)
1368 : memory_tracker_managed_(
1369 new MemoryTypeTracker(memory_tracker
, MemoryTracker::kManaged
)),
1370 memory_tracker_unmanaged_(
1371 new MemoryTypeTracker(memory_tracker
, MemoryTracker::kUnmanaged
)),
1372 memory_tracker_(memory_tracker
),
1373 feature_info_(feature_info
),
1374 framebuffer_manager_(NULL
),
1375 max_texture_size_(max_texture_size
),
1376 max_cube_map_texture_size_(max_cube_map_texture_size
),
1377 max_rectangle_texture_size_(max_rectangle_texture_size
),
1378 max_3d_texture_size_(max_3d_texture_size
),
1379 max_levels_(ComputeMipMapCount(GL_TEXTURE_2D
,
1383 max_cube_map_levels_(ComputeMipMapCount(GL_TEXTURE_CUBE_MAP
,
1384 max_cube_map_texture_size
,
1385 max_cube_map_texture_size
,
1386 max_cube_map_texture_size
)),
1387 max_3d_levels_(ComputeMipMapCount(GL_TEXTURE_3D
,
1388 // Same as GL_TEXTURE_2D_ARRAY
1389 max_3d_texture_size
,
1390 max_3d_texture_size
,
1391 max_3d_texture_size
)),
1392 use_default_textures_(use_default_textures
),
1393 num_unrenderable_textures_(0),
1394 num_unsafe_textures_(0),
1395 num_uncleared_mips_(0),
1398 have_context_(true) {
1399 for (int ii
= 0; ii
< kNumDefaultTextures
; ++ii
) {
1400 black_texture_ids_
[ii
] = 0;
1404 bool TextureManager::Initialize() {
1405 // TODO(gman): The default textures have to be real textures, not the 0
1406 // texture because we simulate non shared resources on top of shared
1407 // resources and all contexts that share resource share the same default
1409 default_textures_
[kTexture2D
] = CreateDefaultAndBlackTextures(
1410 GL_TEXTURE_2D
, &black_texture_ids_
[kTexture2D
]);
1411 default_textures_
[kCubeMap
] = CreateDefaultAndBlackTextures(
1412 GL_TEXTURE_CUBE_MAP
, &black_texture_ids_
[kCubeMap
]);
1414 if (feature_info_
->IsES3Enabled()) {
1415 default_textures_
[kTexture3D
] = CreateDefaultAndBlackTextures(
1416 GL_TEXTURE_3D
, &black_texture_ids_
[kTexture3D
]);
1417 default_textures_
[kTexture2DArray
] = CreateDefaultAndBlackTextures(
1418 GL_TEXTURE_2D_ARRAY
, &black_texture_ids_
[kTexture2DArray
]);
1421 if (feature_info_
->feature_flags().oes_egl_image_external
) {
1422 default_textures_
[kExternalOES
] = CreateDefaultAndBlackTextures(
1423 GL_TEXTURE_EXTERNAL_OES
, &black_texture_ids_
[kExternalOES
]);
1426 if (feature_info_
->feature_flags().arb_texture_rectangle
) {
1427 default_textures_
[kRectangleARB
] = CreateDefaultAndBlackTextures(
1428 GL_TEXTURE_RECTANGLE_ARB
, &black_texture_ids_
[kRectangleARB
]);
1431 // When created from InProcessCommandBuffer, we won't have a |memory_tracker_|
1432 // so don't register a dump provider.
1433 if (memory_tracker_
) {
1434 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
1435 this, base::ThreadTaskRunnerHandle::Get());
1441 scoped_refptr
<TextureRef
>
1442 TextureManager::CreateDefaultAndBlackTextures(
1444 GLuint
* black_texture
) {
1445 static uint8 black
[] = {0, 0, 0, 255};
1447 // Sampling a texture not associated with any EGLImage sibling will return
1448 // black values according to the spec.
1449 bool needs_initialization
= (target
!= GL_TEXTURE_EXTERNAL_OES
);
1450 bool needs_faces
= (target
== GL_TEXTURE_CUBE_MAP
);
1451 bool is_3d_or_2d_array_target
= (target
== GL_TEXTURE_3D
||
1452 target
== GL_TEXTURE_2D_ARRAY
);
1454 // Make default textures and texture for replacing non-renderable textures.
1456 const int num_ids
= use_default_textures_
? 2 : 1;
1457 glGenTextures(num_ids
, ids
);
1458 for (int ii
= 0; ii
< num_ids
; ++ii
) {
1459 glBindTexture(target
, ids
[ii
]);
1460 if (needs_initialization
) {
1462 for (int jj
= 0; jj
< GLES2Util::kNumFaces
; ++jj
) {
1463 glTexImage2D(GLES2Util::IndexToGLFaceTarget(jj
), 0, GL_RGBA
, 1, 1, 0,
1464 GL_RGBA
, GL_UNSIGNED_BYTE
, black
);
1467 if (is_3d_or_2d_array_target
) {
1468 glTexImage3D(target
, 0, GL_RGBA
, 1, 1, 1, 0, GL_RGBA
,
1469 GL_UNSIGNED_BYTE
, black
);
1471 glTexImage2D(target
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
,
1472 GL_UNSIGNED_BYTE
, black
);
1477 glBindTexture(target
, 0);
1479 scoped_refptr
<TextureRef
> default_texture
;
1480 if (use_default_textures_
) {
1481 default_texture
= TextureRef::Create(this, 0, ids
[1]);
1482 SetTarget(default_texture
.get(), target
);
1484 for (int ii
= 0; ii
< GLES2Util::kNumFaces
; ++ii
) {
1485 SetLevelInfo(default_texture
.get(), GLES2Util::IndexToGLFaceTarget(ii
),
1486 0, GL_RGBA
, 1, 1, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
,
1490 if (needs_initialization
) {
1491 SetLevelInfo(default_texture
.get(), GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 1,
1492 0, GL_RGBA
, GL_UNSIGNED_BYTE
, gfx::Rect(1, 1));
1494 SetLevelInfo(default_texture
.get(), GL_TEXTURE_EXTERNAL_OES
, 0, GL_RGBA
,
1495 1, 1, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, gfx::Rect(1, 1));
1500 *black_texture
= ids
[0];
1501 return default_texture
;
1504 bool TextureManager::ValidForTarget(
1505 GLenum target
, GLint level
, GLsizei width
, GLsizei height
, GLsizei depth
) {
1506 GLsizei max_size
= MaxSizeForTarget(target
) >> level
;
1507 return level
>= 0 &&
1511 level
< MaxLevelsForTarget(target
) &&
1512 width
<= max_size
&&
1513 height
<= max_size
&&
1514 depth
<= max_size
&&
1515 (level
== 0 || feature_info_
->feature_flags().npot_ok
||
1516 (!GLES2Util::IsNPOT(width
) &&
1517 !GLES2Util::IsNPOT(height
) &&
1518 !GLES2Util::IsNPOT(depth
))) &&
1519 (target
!= GL_TEXTURE_CUBE_MAP
|| (width
== height
&& depth
== 1)) &&
1520 (target
!= GL_TEXTURE_2D
|| (depth
== 1));
1523 void TextureManager::SetTarget(TextureRef
* ref
, GLenum target
) {
1526 ->SetTarget(feature_info_
.get(), target
, MaxLevelsForTarget(target
));
1529 void TextureManager::SetLevelClearedRect(TextureRef
* ref
,
1532 const gfx::Rect
& cleared_rect
) {
1534 ref
->texture()->SetLevelClearedRect(target
, level
, cleared_rect
);
1537 void TextureManager::SetLevelCleared(TextureRef
* ref
,
1542 ref
->texture()->SetLevelCleared(target
, level
, cleared
);
1545 bool TextureManager::ClearRenderableLevels(
1546 GLES2Decoder
* decoder
, TextureRef
* ref
) {
1548 return ref
->texture()->ClearRenderableLevels(decoder
);
1551 bool TextureManager::ClearTextureLevel(
1552 GLES2Decoder
* decoder
, TextureRef
* ref
,
1553 GLenum target
, GLint level
) {
1555 Texture
* texture
= ref
->texture();
1556 if (texture
->num_uncleared_mips() == 0) {
1559 bool result
= texture
->ClearLevel(decoder
, target
, level
);
1560 texture
->UpdateCleared();
1564 void TextureManager::SetLevelInfo(TextureRef
* ref
,
1567 GLenum internal_format
,
1574 const gfx::Rect
& cleared_rect
) {
1575 DCHECK(gfx::Rect(width
, height
).Contains(cleared_rect
));
1577 Texture
* texture
= ref
->texture();
1579 texture
->GetMemTracker()->TrackMemFree(texture
->estimated_size());
1580 texture
->SetLevelInfo(feature_info_
.get(), target
, level
, internal_format
,
1581 width
, height
, depth
, border
, format
, type
,
1583 texture
->GetMemTracker()->TrackMemAlloc(texture
->estimated_size());
1586 Texture
* TextureManager::Produce(TextureRef
* ref
) {
1588 return ref
->texture();
1591 TextureRef
* TextureManager::Consume(
1595 scoped_refptr
<TextureRef
> ref(new TextureRef(this, client_id
, texture
));
1596 bool result
= textures_
.insert(std::make_pair(client_id
, ref
)).second
;
1601 void TextureManager::SetParameteri(
1602 const char* function_name
, ErrorState
* error_state
,
1603 TextureRef
* ref
, GLenum pname
, GLint param
) {
1604 DCHECK(error_state
);
1606 Texture
* texture
= ref
->texture();
1607 GLenum result
= texture
->SetParameteri(feature_info_
.get(), pname
, param
);
1608 if (result
!= GL_NO_ERROR
) {
1609 if (result
== GL_INVALID_ENUM
) {
1610 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1611 error_state
, function_name
, param
, "param");
1613 ERRORSTATE_SET_GL_ERROR_INVALID_PARAMI(
1614 error_state
, result
, function_name
, pname
, param
);
1617 // Texture tracking pools exist only for the command decoder, so
1618 // do not pass them on to the native GL implementation.
1619 if (pname
!= GL_TEXTURE_POOL_CHROMIUM
) {
1620 glTexParameteri(texture
->target(), pname
, param
);
1625 void TextureManager::SetParameterf(
1626 const char* function_name
, ErrorState
* error_state
,
1627 TextureRef
* ref
, GLenum pname
, GLfloat param
) {
1628 DCHECK(error_state
);
1630 Texture
* texture
= ref
->texture();
1631 GLenum result
= texture
->SetParameterf(feature_info_
.get(), pname
, param
);
1632 if (result
!= GL_NO_ERROR
) {
1633 if (result
== GL_INVALID_ENUM
) {
1634 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1635 error_state
, function_name
, pname
, "pname");
1637 ERRORSTATE_SET_GL_ERROR_INVALID_PARAMF(
1638 error_state
, result
, function_name
, pname
, param
);
1641 // Texture tracking pools exist only for the command decoder, so
1642 // do not pass them on to the native GL implementation.
1643 if (pname
!= GL_TEXTURE_POOL_CHROMIUM
) {
1644 glTexParameterf(texture
->target(), pname
, param
);
1649 bool TextureManager::MarkMipmapsGenerated(TextureRef
* ref
) {
1651 Texture
* texture
= ref
->texture();
1652 texture
->GetMemTracker()->TrackMemFree(texture
->estimated_size());
1653 bool result
= texture
->MarkMipmapsGenerated(feature_info_
.get());
1654 texture
->GetMemTracker()->TrackMemAlloc(texture
->estimated_size());
1658 TextureRef
* TextureManager::CreateTexture(
1659 GLuint client_id
, GLuint service_id
) {
1660 DCHECK_NE(0u, service_id
);
1661 scoped_refptr
<TextureRef
> ref(TextureRef::Create(
1662 this, client_id
, service_id
));
1663 std::pair
<TextureMap::iterator
, bool> result
=
1664 textures_
.insert(std::make_pair(client_id
, ref
));
1665 DCHECK(result
.second
);
1669 TextureRef
* TextureManager::GetTexture(
1670 GLuint client_id
) const {
1671 TextureMap::const_iterator it
= textures_
.find(client_id
);
1672 return it
!= textures_
.end() ? it
->second
.get() : NULL
;
1675 void TextureManager::RemoveTexture(GLuint client_id
) {
1676 TextureMap::iterator it
= textures_
.find(client_id
);
1677 if (it
!= textures_
.end()) {
1678 it
->second
->reset_client_id();
1679 textures_
.erase(it
);
1683 void TextureManager::StartTracking(TextureRef
* ref
) {
1684 Texture
* texture
= ref
->texture();
1686 num_uncleared_mips_
+= texture
->num_uncleared_mips();
1687 if (!texture
->SafeToRenderFrom())
1688 ++num_unsafe_textures_
;
1689 if (!texture
->CanRender(feature_info_
.get()))
1690 ++num_unrenderable_textures_
;
1691 if (texture
->HasImages())
1695 void TextureManager::StopTracking(TextureRef
* ref
) {
1696 if (ref
->num_observers()) {
1697 for (unsigned int i
= 0; i
< destruction_observers_
.size(); i
++) {
1698 destruction_observers_
[i
]->OnTextureRefDestroying(ref
);
1700 DCHECK_EQ(ref
->num_observers(), 0);
1703 Texture
* texture
= ref
->texture();
1706 if (texture
->HasImages()) {
1707 DCHECK_NE(0, num_images_
);
1710 if (!texture
->CanRender(feature_info_
.get())) {
1711 DCHECK_NE(0, num_unrenderable_textures_
);
1712 --num_unrenderable_textures_
;
1714 if (!texture
->SafeToRenderFrom()) {
1715 DCHECK_NE(0, num_unsafe_textures_
);
1716 --num_unsafe_textures_
;
1718 num_uncleared_mips_
-= texture
->num_uncleared_mips();
1719 DCHECK_GE(num_uncleared_mips_
, 0);
1722 MemoryTypeTracker
* TextureManager::GetMemTracker(GLenum tracking_pool
) {
1723 switch (tracking_pool
) {
1724 case GL_TEXTURE_POOL_MANAGED_CHROMIUM
:
1725 return memory_tracker_managed_
.get();
1727 case GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
:
1728 return memory_tracker_unmanaged_
.get();
1737 Texture
* TextureManager::GetTextureForServiceId(GLuint service_id
) const {
1738 // This doesn't need to be fast. It's only used during slow queries.
1739 for (TextureMap::const_iterator it
= textures_
.begin();
1740 it
!= textures_
.end(); ++it
) {
1741 Texture
* texture
= it
->second
->texture();
1742 if (texture
->service_id() == service_id
)
1748 GLsizei
TextureManager::ComputeMipMapCount(GLenum target
,
1753 case GL_TEXTURE_EXTERNAL_OES
:
1757 base::bits::Log2Floor(std::max(std::max(width
, height
), depth
));
1761 void TextureManager::SetLevelImage(
1765 gfx::GLImage
* image
) {
1767 ref
->texture()->SetLevelImage(feature_info_
.get(), target
, level
, image
);
1770 size_t TextureManager::GetSignatureSize() const {
1771 return sizeof(TextureTag
) + sizeof(TextureSignature
);
1774 void TextureManager::AddToSignature(
1778 std::string
* signature
) const {
1779 ref
->texture()->AddToSignature(feature_info_
.get(), target
, level
, signature
);
1782 void TextureManager::UpdateSafeToRenderFrom(int delta
) {
1783 num_unsafe_textures_
+= delta
;
1784 DCHECK_GE(num_unsafe_textures_
, 0);
1787 void TextureManager::UpdateUnclearedMips(int delta
) {
1788 num_uncleared_mips_
+= delta
;
1789 DCHECK_GE(num_uncleared_mips_
, 0);
1792 void TextureManager::UpdateCanRenderCondition(
1793 Texture::CanRenderCondition old_condition
,
1794 Texture::CanRenderCondition new_condition
) {
1795 if (old_condition
== Texture::CAN_RENDER_NEVER
||
1796 (old_condition
== Texture::CAN_RENDER_ONLY_IF_NPOT
&&
1797 !feature_info_
->feature_flags().npot_ok
)) {
1798 DCHECK_GT(num_unrenderable_textures_
, 0);
1799 --num_unrenderable_textures_
;
1801 if (new_condition
== Texture::CAN_RENDER_NEVER
||
1802 (new_condition
== Texture::CAN_RENDER_ONLY_IF_NPOT
&&
1803 !feature_info_
->feature_flags().npot_ok
))
1804 ++num_unrenderable_textures_
;
1807 void TextureManager::UpdateNumImages(int delta
) {
1808 num_images_
+= delta
;
1809 DCHECK_GE(num_images_
, 0);
1812 void TextureManager::IncFramebufferStateChangeCount() {
1813 if (framebuffer_manager_
)
1814 framebuffer_manager_
->IncFramebufferStateChangeCount();
1817 bool TextureManager::ValidateFormatAndTypeCombination(
1818 ErrorState
* error_state
, const char* function_name
, GLenum format
,
1820 // TODO(zmo): now this is only called by GLES2DecoderImpl::DoCopyTexImage2D
1821 // and is incorrect for ES3. Fix this.
1822 if (!g_format_type_validator
.Get().IsValid(format
, format
, type
)) {
1823 ERRORSTATE_SET_GL_ERROR(
1824 error_state
, GL_INVALID_OPERATION
, function_name
,
1825 (std::string("invalid type ") +
1826 GLES2Util::GetStringEnum(type
) + " for format " +
1827 GLES2Util::GetStringEnum(format
)).c_str());
1833 bool TextureManager::ValidateTextureParameters(
1834 ErrorState
* error_state
, const char* function_name
,
1835 GLenum format
, GLenum type
, GLenum internal_format
, GLint level
) {
1836 const Validators
* validators
= feature_info_
->validators();
1837 if (!validators
->texture_format
.IsValid(format
)) {
1838 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1839 error_state
, function_name
, format
, "format");
1842 if (!validators
->pixel_type
.IsValid(type
)) {
1843 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1844 error_state
, function_name
, type
, "type");
1847 if (!g_format_type_validator
.Get().IsValid(internal_format
, format
, type
)) {
1848 ERRORSTATE_SET_GL_ERROR(
1849 error_state
, GL_INVALID_OPERATION
, function_name
,
1850 "invalid internalformat/format/type combination");
1853 // For TexSubImage calls, internal_format isn't part of the parameters,
1854 // so its validation needs to be after the internal_format/format/type
1855 // combination validation. Otherwise, an unexpected INVALID_ENUM could be
1856 // generated instead of INVALID_OPERATION.
1857 if (!validators
->texture_internal_format
.IsValid(internal_format
)) {
1858 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1859 error_state
, function_name
, internal_format
, "internal_format");
1862 if (!feature_info_
->IsES3Enabled()) {
1863 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
1864 if ((channels
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0 && level
) {
1865 ERRORSTATE_SET_GL_ERROR(
1866 error_state
, GL_INVALID_OPERATION
, function_name
,
1867 (std::string("invalid format ") + GLES2Util::GetStringEnum(format
) +
1868 " for level != 0").c_str());
1875 // Gets the texture id for a given target.
1876 TextureRef
* TextureManager::GetTextureInfoForTarget(
1877 ContextState
* state
, GLenum target
) {
1878 TextureUnit
& unit
= state
->texture_units
[state
->active_texture_unit
];
1879 TextureRef
* texture
= NULL
;
1882 texture
= unit
.bound_texture_2d
.get();
1884 case GL_TEXTURE_CUBE_MAP
:
1885 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
1886 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
1887 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
1888 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
1889 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
1890 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
1891 texture
= unit
.bound_texture_cube_map
.get();
1893 case GL_TEXTURE_EXTERNAL_OES
:
1894 texture
= unit
.bound_texture_external_oes
.get();
1896 case GL_TEXTURE_RECTANGLE_ARB
:
1897 texture
= unit
.bound_texture_rectangle_arb
.get();
1900 texture
= unit
.bound_texture_3d
.get();
1902 case GL_TEXTURE_2D_ARRAY
:
1903 texture
= unit
.bound_texture_2d_array
.get();
1912 TextureRef
* TextureManager::GetTextureInfoForTargetUnlessDefault(
1913 ContextState
* state
, GLenum target
) {
1914 TextureRef
* texture
= GetTextureInfoForTarget(state
, target
);
1917 if (texture
== GetDefaultTextureInfo(target
))
1922 bool TextureManager::ValidateTexImage(
1923 ContextState
* state
,
1924 const char* function_name
,
1925 const DoTexImageArguments
& args
,
1926 TextureRef
** texture_ref
) {
1927 ErrorState
* error_state
= state
->GetErrorState();
1928 const Validators
* validators
= feature_info_
->validators();
1929 if (((args
.command_type
== DoTexImageArguments::kTexImage2D
) &&
1930 !validators
->texture_target
.IsValid(args
.target
)) ||
1931 ((args
.command_type
== DoTexImageArguments::kTexImage3D
) &&
1932 !validators
->texture_3_d_target
.IsValid(args
.target
))) {
1933 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1934 error_state
, function_name
, args
.target
, "target");
1937 if (!ValidateTextureParameters(
1938 error_state
, function_name
, args
.format
, args
.type
,
1939 args
.internal_format
, args
.level
)) {
1942 if (!ValidForTarget(args
.target
, args
.level
,
1943 args
.width
, args
.height
, args
.depth
) ||
1945 ERRORSTATE_SET_GL_ERROR(
1946 error_state
, GL_INVALID_VALUE
, function_name
,
1947 "dimensions out of range");
1950 if ((GLES2Util::GetChannelsForFormat(args
.format
) &
1951 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0 && args
.pixels
1952 && !feature_info_
->IsES3Enabled()) {
1953 ERRORSTATE_SET_GL_ERROR(
1954 error_state
, GL_INVALID_OPERATION
,
1955 function_name
, "can not supply data for depth or stencil textures");
1959 TextureRef
* local_texture_ref
= GetTextureInfoForTarget(state
, args
.target
);
1960 if (!local_texture_ref
) {
1961 ERRORSTATE_SET_GL_ERROR(
1962 error_state
, GL_INVALID_OPERATION
, function_name
,
1963 "unknown texture for target");
1966 if (local_texture_ref
->texture()->IsImmutable()) {
1967 ERRORSTATE_SET_GL_ERROR(
1968 error_state
, GL_INVALID_OPERATION
, function_name
,
1969 "texture is immutable");
1973 if (!memory_tracker_managed_
->EnsureGPUMemoryAvailable(args
.pixels_size
)) {
1974 ERRORSTATE_SET_GL_ERROR(error_state
, GL_OUT_OF_MEMORY
, function_name
,
1979 // Write the TextureReference since this is valid.
1980 *texture_ref
= local_texture_ref
;
1984 void TextureManager::ValidateAndDoTexImage(
1985 DecoderTextureState
* texture_state
,
1986 ContextState
* state
,
1987 DecoderFramebufferState
* framebuffer_state
,
1988 const char* function_name
,
1989 const DoTexImageArguments
& args
) {
1990 TextureRef
* texture_ref
;
1991 if (!ValidateTexImage(state
, function_name
, args
, &texture_ref
)) {
1995 // ValidateTexImage is passed already.
1996 Texture
* texture
= texture_ref
->texture();
1997 bool need_cube_map_workaround
=
1998 texture
->target() == GL_TEXTURE_CUBE_MAP
&&
1999 (texture_state
->force_cube_complete
||
2000 (texture_state
->force_cube_map_positive_x_allocation
&&
2001 args
.target
!= GL_TEXTURE_CUBE_MAP_POSITIVE_X
));
2002 if (need_cube_map_workaround
) {
2003 std::vector
<GLenum
> undefined_faces
;
2004 if (texture_state
->force_cube_complete
) {
2007 for (unsigned i
= 0; i
< 6; i
++) {
2009 texture
->GetLevelSize(GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
,
2010 args
.level
, &width
, &height
, nullptr);
2011 if (!defined
|| GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
== args
.target
)
2012 undefined_faces
.push_back(GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
);
2014 } else if (texture_state
->force_cube_map_positive_x_allocation
&&
2015 args
.target
!= GL_TEXTURE_CUBE_MAP_POSITIVE_X
) {
2018 if (!texture
->GetLevelSize(GL_TEXTURE_CUBE_MAP_POSITIVE_X
, args
.level
,
2019 &width
, &height
, nullptr)) {
2020 undefined_faces
.push_back(GL_TEXTURE_CUBE_MAP_POSITIVE_X
);
2022 undefined_faces
.push_back(args
.target
);
2025 DCHECK(undefined_faces
.size());
2026 if (!memory_tracker_managed_
->EnsureGPUMemoryAvailable(
2027 undefined_faces
.size() * args
.pixels_size
)) {
2028 ERRORSTATE_SET_GL_ERROR(state
->GetErrorState(), GL_OUT_OF_MEMORY
,
2029 function_name
, "out of memory");
2032 DoTexImageArguments new_args
= args
;
2033 scoped_ptr
<char[]> zero(new char[args
.pixels_size
]);
2034 memset(zero
.get(), 0, args
.pixels_size
);
2035 for (GLenum face
: undefined_faces
) {
2036 new_args
.target
= face
;
2037 if (face
== args
.target
) {
2038 new_args
.pixels
= args
.pixels
;
2040 new_args
.pixels
= zero
.get();
2042 DoTexImage(texture_state
, state
->GetErrorState(), framebuffer_state
,
2043 function_name
, texture_ref
, new_args
);
2048 DoTexImage(texture_state
, state
->GetErrorState(), framebuffer_state
,
2049 function_name
, texture_ref
, args
);
2052 GLenum
TextureManager::AdjustTexFormat(GLenum format
) const {
2053 // TODO(bajones): GLES 3 allows for internal format and format to differ.
2054 // This logic may need to change as a result.
2055 if (gfx::GetGLImplementation() == gfx::kGLImplementationDesktopGL
) {
2056 if (format
== GL_SRGB_EXT
)
2058 if (format
== GL_SRGB_ALPHA_EXT
)
2064 void TextureManager::DoTexImage(
2065 DecoderTextureState
* texture_state
,
2066 ErrorState
* error_state
,
2067 DecoderFramebufferState
* framebuffer_state
,
2068 const char* function_name
,
2069 TextureRef
* texture_ref
,
2070 const DoTexImageArguments
& args
) {
2071 Texture
* texture
= texture_ref
->texture();
2072 GLsizei tex_width
= 0;
2073 GLsizei tex_height
= 0;
2074 GLsizei tex_depth
= 0;
2075 GLenum tex_type
= 0;
2076 GLenum tex_format
= 0;
2077 bool level_is_same
=
2078 texture
->GetLevelSize(
2079 args
.target
, args
.level
, &tex_width
, &tex_height
, &tex_depth
) &&
2080 texture
->GetLevelType(args
.target
, args
.level
, &tex_type
, &tex_format
) &&
2081 args
.width
== tex_width
&& args
.height
== tex_height
&&
2082 args
.depth
== tex_depth
&& args
.type
== tex_type
&&
2083 args
.format
== tex_format
;
2085 if (level_is_same
&& !args
.pixels
) {
2086 // Just set the level texture but mark the texture as uncleared.
2087 SetLevelInfo(texture_ref
, args
.target
, args
.level
, args
.internal_format
,
2088 args
.width
, args
.height
, args
.depth
, args
.border
, args
.format
,
2089 args
.type
, gfx::Rect());
2090 texture_state
->tex_image_failed
= false;
2094 if (texture
->IsAttachedToFramebuffer()) {
2095 framebuffer_state
->clear_state_dirty
= true;
2098 if (texture_state
->texsubimage_faster_than_teximage
&&
2099 level_is_same
&& args
.pixels
) {
2101 ScopedTextureUploadTimer
timer(texture_state
);
2102 if (args
.command_type
== DoTexImageArguments::kTexImage3D
) {
2103 glTexSubImage3D(args
.target
, args
.level
, 0, 0, 0,
2104 args
.width
, args
.height
, args
.depth
,
2105 args
.format
, args
.type
, args
.pixels
);
2107 glTexSubImage2D(args
.target
, args
.level
, 0, 0, args
.width
, args
.height
,
2108 AdjustTexFormat(args
.format
), args
.type
, args
.pixels
);
2111 SetLevelCleared(texture_ref
, args
.target
, args
.level
, true);
2112 texture_state
->tex_image_failed
= false;
2116 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state
, function_name
);
2118 ScopedTextureUploadTimer
timer(texture_state
);
2119 if (args
.command_type
== DoTexImageArguments::kTexImage3D
) {
2120 glTexImage3D(args
.target
, args
.level
, args
.internal_format
, args
.width
,
2121 args
.height
, args
.depth
, args
.border
, args
.format
,
2122 args
.type
, args
.pixels
);
2124 glTexImage2D(args
.target
, args
.level
, args
.internal_format
, args
.width
,
2125 args
.height
, args
.border
, AdjustTexFormat(args
.format
),
2126 args
.type
, args
.pixels
);
2129 GLenum error
= ERRORSTATE_PEEK_GL_ERROR(error_state
, function_name
);
2130 if (error
== GL_NO_ERROR
) {
2132 texture_ref
, args
.target
, args
.level
, args
.internal_format
, args
.width
,
2133 args
.height
, args
.depth
, args
.border
, args
.format
, args
.type
,
2134 args
.pixels
!= NULL
? gfx::Rect(args
.width
, args
.height
) : gfx::Rect());
2135 texture_state
->tex_image_failed
= false;
2139 ScopedTextureUploadTimer::ScopedTextureUploadTimer(
2140 DecoderTextureState
* texture_state
)
2141 : texture_state_(texture_state
),
2142 begin_time_(base::TimeTicks::Now()) {
2145 ScopedTextureUploadTimer::~ScopedTextureUploadTimer() {
2146 texture_state_
->texture_upload_count
++;
2147 texture_state_
->total_texture_upload_time
+=
2148 base::TimeTicks::Now() - begin_time_
;
2151 bool TextureManager::OnMemoryDump(const base::trace_event::MemoryDumpArgs
& args
,
2152 base::trace_event::ProcessMemoryDump
* pmd
) {
2153 for (const auto& resource
: textures_
) {
2154 // Only dump memory info for textures actually owned by this TextureManager.
2155 DumpTextureRef(pmd
, resource
.second
.get());
2158 // Also dump TextureManager internal textures, if allocated.
2159 for (int i
= 0; i
< kNumDefaultTextures
; i
++) {
2160 if (default_textures_
[i
]) {
2161 DumpTextureRef(pmd
, default_textures_
[i
].get());
2168 void TextureManager::DumpTextureRef(base::trace_event::ProcessMemoryDump
* pmd
,
2170 uint32_t size
= ref
->texture()->estimated_size();
2172 // Ignore unallocated texture IDs.
2176 std::string dump_name
=
2177 base::StringPrintf("gpu/gl/textures/client_%d/texture_%d",
2178 memory_tracker_
->ClientId(), ref
->client_id());
2180 base::trace_event::MemoryAllocatorDump
* dump
=
2181 pmd
->CreateAllocatorDump(dump_name
);
2182 dump
->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize
,
2183 base::trace_event::MemoryAllocatorDump::kUnitsBytes
,
2184 static_cast<uint64_t>(size
));
2186 // Add the |client_guid| which expresses shared ownership with the client
2188 auto client_guid
= gfx::GetGLTextureClientGUIDForTracing(
2189 memory_tracker_
->ShareGroupTracingGUID(), ref
->client_id());
2190 pmd
->CreateSharedGlobalAllocatorDump(client_guid
);
2191 pmd
->AddOwnershipEdge(dump
->guid(), client_guid
);
2193 // Add a |service_guid| which expresses shared ownership between the various
2195 // TODO(ericrk): May need to ensure uniqueness using GLShareGroup and
2196 // potentially cross-share-group sharing via EGLImages. crbug.com/512534
2197 auto service_guid
= gfx::GetGLTextureServiceGUIDForTracing(
2198 memory_tracker_
->ShareGroupTracingGUID(), ref
->texture()->service_id());
2199 pmd
->CreateSharedGlobalAllocatorDump(service_guid
);
2201 int importance
= 0; // Default importance.
2202 // The link to the memory tracking |client_id| is given a higher importance
2204 if (ref
== ref
->texture()->memory_tracking_ref_
)
2207 pmd
->AddOwnershipEdge(client_guid
, service_guid
, importance
);
2209 // Dump all sub-levels held by the texture. They will appear below the main
2210 // gl/textures/client_X/texture_Y dump.
2211 ref
->texture()->DumpLevelMemory(pmd
, memory_tracker_
->ClientTracingId(),
2215 } // namespace gles2