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
;
446 if (target_
== GL_TEXTURE_CUBE_MAP
&& !cube_complete())
447 return CAN_RENDER_NEVER
;
450 bool is_npot_compatible
= !needs_mips
&&
451 wrap_s_
== GL_CLAMP_TO_EDGE
&&
452 wrap_t_
== GL_CLAMP_TO_EDGE
;
454 if (!is_npot_compatible
) {
455 if (target_
== GL_TEXTURE_RECTANGLE_ARB
)
456 return CAN_RENDER_NEVER
;
458 return CAN_RENDER_ONLY_IF_NPOT
;
461 return CAN_RENDER_ALWAYS
;
464 bool Texture::CanRender(const FeatureInfo
* feature_info
) const {
465 switch (can_render_condition_
) {
466 case CAN_RENDER_ALWAYS
:
468 case CAN_RENDER_NEVER
:
470 case CAN_RENDER_ONLY_IF_NPOT
:
473 return feature_info
->feature_flags().npot_ok
;
476 void Texture::AddToSignature(
477 const FeatureInfo
* feature_info
,
480 std::string
* signature
) const {
481 DCHECK(feature_info
);
484 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
485 DCHECK_LT(static_cast<size_t>(face_index
),
487 DCHECK_LT(static_cast<size_t>(level
),
488 face_infos_
[face_index
].level_infos
.size());
490 const Texture::LevelInfo
& info
=
491 face_infos_
[face_index
].level_infos
[level
];
493 TextureSignature
signature_data(target
,
501 info
.internal_format
,
514 info
.image
.get() != NULL
,
515 CanRender(feature_info
),
519 signature
->append(TextureTag
, sizeof(TextureTag
));
520 signature
->append(reinterpret_cast<const char*>(&signature_data
),
521 sizeof(signature_data
));
524 void Texture::SetMailboxManager(MailboxManager
* mailbox_manager
) {
525 DCHECK(!mailbox_manager_
|| mailbox_manager_
== mailbox_manager
);
526 mailbox_manager_
= mailbox_manager
;
529 bool Texture::MarkMipmapsGenerated(
530 const FeatureInfo
* feature_info
) {
531 if (!CanGenerateMipmaps(feature_info
)) {
534 for (size_t ii
= 0; ii
< face_infos_
.size(); ++ii
) {
535 const Texture::FaceInfo
& face_info
= face_infos_
[ii
];
536 const Texture::LevelInfo
& level0_info
= face_info
.level_infos
[0];
537 GLsizei width
= level0_info
.width
;
538 GLsizei height
= level0_info
.height
;
539 GLsizei depth
= level0_info
.depth
;
540 GLenum target
= target_
== GL_TEXTURE_2D
? GL_TEXTURE_2D
:
541 GLES2Util::IndexToGLFaceTarget(ii
);
543 const GLsizei num_mips
= face_info
.num_mip_levels
;
544 for (GLsizei level
= 1; level
< num_mips
; ++level
) {
545 width
= std::max(1, width
>> 1);
546 height
= std::max(1, height
>> 1);
547 depth
= std::max(1, depth
>> 1);
548 SetLevelInfo(feature_info
, target
, level
, level0_info
.internal_format
,
549 width
, height
, depth
, level0_info
.border
, level0_info
.format
,
550 level0_info
.type
, gfx::Rect(width
, height
));
557 void Texture::SetTarget(
558 const FeatureInfo
* feature_info
, GLenum target
, GLint max_levels
) {
559 DCHECK_EQ(0u, target_
); // you can only set this once.
561 size_t num_faces
= (target
== GL_TEXTURE_CUBE_MAP
) ? 6 : 1;
562 face_infos_
.resize(num_faces
);
563 for (size_t ii
= 0; ii
< num_faces
; ++ii
) {
564 face_infos_
[ii
].level_infos
.resize(max_levels
);
567 if (target
== GL_TEXTURE_EXTERNAL_OES
|| target
== GL_TEXTURE_RECTANGLE_ARB
) {
568 min_filter_
= GL_LINEAR
;
569 wrap_s_
= wrap_t_
= GL_CLAMP_TO_EDGE
;
572 if (target
== GL_TEXTURE_EXTERNAL_OES
) {
575 Update(feature_info
);
576 UpdateCanRenderCondition();
579 bool Texture::CanGenerateMipmaps(
580 const FeatureInfo
* feature_info
) const {
581 if ((npot() && !feature_info
->feature_flags().npot_ok
) ||
582 face_infos_
.empty() ||
583 target_
== GL_TEXTURE_EXTERNAL_OES
||
584 target_
== GL_TEXTURE_RECTANGLE_ARB
) {
588 // Can't generate mips for depth or stencil textures.
589 const Texture::LevelInfo
& first
= face_infos_
[0].level_infos
[0];
590 uint32 channels
= GLES2Util::GetChannelsForFormat(first
.format
);
591 if (channels
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) {
595 // TODO(gman): Check internal_format, format and type.
596 for (size_t ii
= 0; ii
< face_infos_
.size(); ++ii
) {
597 const LevelInfo
& info
= face_infos_
[ii
].level_infos
[0];
598 if ((info
.target
== 0) || (info
.width
!= first
.width
) ||
599 (info
.height
!= first
.height
) || (info
.depth
!= 1) ||
600 (info
.format
!= first
.format
) ||
601 (info
.internal_format
!= first
.internal_format
) ||
602 (info
.type
!= first
.type
) ||
603 feature_info
->validators()->compressed_texture_format
.IsValid(
604 info
.internal_format
) ||
612 bool Texture::TextureIsNPOT(GLsizei width
,
615 return (GLES2Util::IsNPOT(width
) ||
616 GLES2Util::IsNPOT(height
) ||
617 GLES2Util::IsNPOT(depth
));
620 bool Texture::TextureFaceComplete(const Texture::LevelInfo
& first_face
,
623 GLenum internal_format
,
629 bool complete
= (target
!= 0 && depth
== 1);
630 if (face_index
!= 0) {
631 complete
&= (width
== first_face
.width
&&
632 height
== first_face
.height
&&
633 internal_format
== first_face
.internal_format
&&
634 format
== first_face
.format
&&
635 type
== first_face
.type
);
640 bool Texture::TextureMipComplete(const Texture::LevelInfo
& level0_face
,
643 GLenum internal_format
,
649 bool complete
= (target
!= 0);
651 const GLsizei mip_width
= std::max(1, level0_face
.width
>> level
);
652 const GLsizei mip_height
= std::max(1, level0_face
.height
>> level
);
653 const GLsizei mip_depth
= std::max(1, level0_face
.depth
>> level
);
655 complete
&= (width
== mip_width
&&
656 height
== mip_height
&&
657 depth
== mip_depth
&&
658 internal_format
== level0_face
.internal_format
&&
659 format
== level0_face
.format
&&
660 type
== level0_face
.type
);
665 void Texture::SetLevelClearedRect(GLenum target
,
667 const gfx::Rect
& cleared_rect
) {
669 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
670 DCHECK_LT(static_cast<size_t>(face_index
),
672 DCHECK_LT(static_cast<size_t>(level
),
673 face_infos_
[face_index
].level_infos
.size());
674 Texture::LevelInfo
& info
=
675 face_infos_
[face_index
].level_infos
[level
];
676 UpdateMipCleared(&info
, info
.width
, info
.height
, cleared_rect
);
680 void Texture::SetLevelCleared(GLenum target
, GLint level
, bool cleared
) {
682 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
683 DCHECK_LT(static_cast<size_t>(face_index
), face_infos_
.size());
684 DCHECK_LT(static_cast<size_t>(level
),
685 face_infos_
[face_index
].level_infos
.size());
686 Texture::LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
687 UpdateMipCleared(&info
, info
.width
, info
.height
,
688 cleared
? gfx::Rect(info
.width
, info
.height
) : gfx::Rect());
692 void Texture::UpdateCleared() {
693 if (face_infos_
.empty()) {
697 const bool cleared
= (num_uncleared_mips_
== 0);
699 // If texture is uncleared and is attached to a framebuffer,
700 // that framebuffer must be marked possibly incomplete.
701 if (!cleared
&& IsAttachedToFramebuffer()) {
702 IncAllFramebufferStateChangeCount();
705 UpdateSafeToRenderFrom(cleared
);
708 void Texture::UpdateSafeToRenderFrom(bool cleared
) {
709 if (cleared_
== cleared
)
712 int delta
= cleared
? -1 : +1;
713 for (RefSet::iterator it
= refs_
.begin(); it
!= refs_
.end(); ++it
)
714 (*it
)->manager()->UpdateSafeToRenderFrom(delta
);
717 void Texture::UpdateMipCleared(LevelInfo
* info
,
720 const gfx::Rect
& cleared_rect
) {
721 bool was_cleared
= info
->cleared_rect
== gfx::Rect(info
->width
, info
->height
);
723 info
->height
= height
;
724 info
->cleared_rect
= cleared_rect
;
725 bool cleared
= info
->cleared_rect
== gfx::Rect(info
->width
, info
->height
);
726 if (cleared
== was_cleared
)
728 int delta
= cleared
? -1 : +1;
729 num_uncleared_mips_
+= delta
;
730 for (RefSet::iterator it
= refs_
.begin(); it
!= refs_
.end(); ++it
)
731 (*it
)->manager()->UpdateUnclearedMips(delta
);
734 void Texture::UpdateCanRenderCondition() {
735 CanRenderCondition can_render_condition
= GetCanRenderCondition();
736 if (can_render_condition_
== can_render_condition
)
738 for (RefSet::iterator it
= refs_
.begin(); it
!= refs_
.end(); ++it
)
739 (*it
)->manager()->UpdateCanRenderCondition(can_render_condition_
,
740 can_render_condition
);
741 can_render_condition_
= can_render_condition
;
744 void Texture::UpdateHasImages() {
745 if (face_infos_
.empty())
748 bool has_images
= false;
749 for (size_t ii
= 0; ii
< face_infos_
.size(); ++ii
) {
750 for (size_t jj
= 0; jj
< face_infos_
[ii
].level_infos
.size(); ++jj
) {
751 const Texture::LevelInfo
& info
= face_infos_
[ii
].level_infos
[jj
];
752 if (info
.image
.get() != NULL
) {
759 if (has_images_
== has_images
)
761 has_images_
= has_images
;
762 int delta
= has_images
? +1 : -1;
763 for (RefSet::iterator it
= refs_
.begin(); it
!= refs_
.end(); ++it
)
764 (*it
)->manager()->UpdateNumImages(delta
);
767 void Texture::IncAllFramebufferStateChangeCount() {
768 for (RefSet::iterator it
= refs_
.begin(); it
!= refs_
.end(); ++it
)
769 (*it
)->manager()->IncFramebufferStateChangeCount();
772 void Texture::SetLevelInfo(const FeatureInfo
* feature_info
,
775 GLenum internal_format
,
782 const gfx::Rect
& cleared_rect
) {
784 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
785 DCHECK_LT(static_cast<size_t>(face_index
),
787 DCHECK_LT(static_cast<size_t>(level
),
788 face_infos_
[face_index
].level_infos
.size());
790 DCHECK_GE(height
, 0);
792 Texture::LevelInfo
& info
=
793 face_infos_
[face_index
].level_infos
[level
];
795 // Update counters only if any attributes have changed. Counters are
796 // comparisons between the old and new values so it must be done before any
797 // assignment has been done to the LevelInfo.
798 if (info
.target
!= target
||
799 info
.internal_format
!= internal_format
||
800 info
.width
!= width
||
801 info
.height
!= height
||
802 info
.depth
!= depth
||
803 info
.format
!= format
||
806 // Calculate the mip level count.
807 face_infos_
[face_index
].num_mip_levels
=
808 TextureManager::ComputeMipMapCount(target_
, width
, height
, depth
);
810 // Update NPOT face count for the first level.
811 bool prev_npot
= TextureIsNPOT(info
.width
, info
.height
, info
.depth
);
812 bool now_npot
= TextureIsNPOT(width
, height
, depth
);
813 if (prev_npot
!= now_npot
)
814 num_npot_faces_
+= now_npot
? 1 : -1;
816 // Signify that level 0 has been changed, so they need to be reverified.
817 texture_level0_dirty_
= true;
820 // Signify that at least one of the mips has changed.
821 texture_mips_dirty_
= true;
824 info
.target
= target
;
826 info
.internal_format
= internal_format
;
828 info
.border
= border
;
829 info
.format
= format
;
833 UpdateMipCleared(&info
, width
, height
, cleared_rect
);
835 estimated_size_
-= info
.estimated_size
;
836 GLES2Util::ComputeImageDataSizes(
837 width
, height
, 1, format
, type
, 4, &info
.estimated_size
, NULL
, NULL
);
838 estimated_size_
+= info
.estimated_size
;
840 max_level_set_
= std::max(max_level_set_
, level
);
841 Update(feature_info
);
843 UpdateCanRenderCondition();
845 if (IsAttachedToFramebuffer()) {
846 // TODO(gman): If textures tracked which framebuffers they were attached to
847 // we could just mark those framebuffers as not complete.
848 IncAllFramebufferStateChangeCount();
852 bool Texture::ValidForTexture(
862 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
863 if (level
>= 0 && face_index
< face_infos_
.size() &&
864 static_cast<size_t>(level
) < face_infos_
[face_index
].level_infos
.size()) {
865 const LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
869 return SafeAddInt32(xoffset
, width
, &max_x
) &&
870 SafeAddInt32(yoffset
, height
, &max_y
) &&
871 SafeAddInt32(zoffset
, depth
, &max_z
) &&
875 max_x
<= info
.width
&&
876 max_y
<= info
.height
&&
877 max_z
<= info
.depth
&&
883 bool Texture::GetLevelSize(
884 GLint target
, GLint level
,
885 GLsizei
* width
, GLsizei
* height
, GLsizei
* depth
) const {
888 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
889 if (level
>= 0 && face_index
< face_infos_
.size() &&
890 static_cast<size_t>(level
) < face_infos_
[face_index
].level_infos
.size()) {
891 const LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
892 if (info
.target
!= 0) {
894 *height
= info
.height
;
903 bool Texture::GetLevelType(
904 GLint target
, GLint level
, GLenum
* type
, GLenum
* internal_format
) const {
906 DCHECK(internal_format
);
907 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
908 if (level
>= 0 && face_index
< face_infos_
.size() &&
909 static_cast<size_t>(level
) < face_infos_
[face_index
].level_infos
.size()) {
910 const LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
911 if (info
.target
!= 0) {
913 *internal_format
= info
.internal_format
;
920 GLenum
Texture::SetParameteri(
921 const FeatureInfo
* feature_info
, GLenum pname
, GLint param
) {
922 DCHECK(feature_info
);
924 if (target_
== GL_TEXTURE_EXTERNAL_OES
||
925 target_
== GL_TEXTURE_RECTANGLE_ARB
) {
926 if (pname
== GL_TEXTURE_MIN_FILTER
&&
927 (param
!= GL_NEAREST
&& param
!= GL_LINEAR
))
928 return GL_INVALID_ENUM
;
929 if ((pname
== GL_TEXTURE_WRAP_S
|| pname
== GL_TEXTURE_WRAP_T
) &&
930 param
!= GL_CLAMP_TO_EDGE
)
931 return GL_INVALID_ENUM
;
935 case GL_TEXTURE_MIN_LOD
:
936 case GL_TEXTURE_MAX_LOD
:
938 GLfloat fparam
= static_cast<GLfloat
>(param
);
939 return SetParameterf(feature_info
, pname
, fparam
);
941 case GL_TEXTURE_MIN_FILTER
:
942 if (!feature_info
->validators()->texture_min_filter_mode
.IsValid(param
)) {
943 return GL_INVALID_ENUM
;
947 case GL_TEXTURE_MAG_FILTER
:
948 if (!feature_info
->validators()->texture_mag_filter_mode
.IsValid(param
)) {
949 return GL_INVALID_ENUM
;
953 case GL_TEXTURE_POOL_CHROMIUM
:
954 if (!feature_info
->validators()->texture_pool
.IsValid(param
)) {
955 return GL_INVALID_ENUM
;
957 GetMemTracker()->TrackMemFree(estimated_size());
959 GetMemTracker()->TrackMemAlloc(estimated_size());
961 case GL_TEXTURE_WRAP_R
:
962 if (!feature_info
->validators()->texture_wrap_mode
.IsValid(param
)) {
963 return GL_INVALID_ENUM
;
967 case GL_TEXTURE_WRAP_S
:
968 if (!feature_info
->validators()->texture_wrap_mode
.IsValid(param
)) {
969 return GL_INVALID_ENUM
;
973 case GL_TEXTURE_WRAP_T
:
974 if (!feature_info
->validators()->texture_wrap_mode
.IsValid(param
)) {
975 return GL_INVALID_ENUM
;
979 case GL_TEXTURE_COMPARE_FUNC
:
980 if (!feature_info
->validators()->texture_compare_func
.IsValid(param
)) {
981 return GL_INVALID_ENUM
;
983 compare_func_
= param
;
985 case GL_TEXTURE_COMPARE_MODE
:
986 if (!feature_info
->validators()->texture_compare_mode
.IsValid(param
)) {
987 return GL_INVALID_ENUM
;
989 compare_mode_
= param
;
991 case GL_TEXTURE_BASE_LEVEL
:
993 return GL_INVALID_VALUE
;
997 case GL_TEXTURE_MAX_LEVEL
:
999 return GL_INVALID_VALUE
;
1003 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
1005 return GL_INVALID_VALUE
;
1008 case GL_TEXTURE_USAGE_ANGLE
:
1009 if (!feature_info
->validators()->texture_usage
.IsValid(param
)) {
1010 return GL_INVALID_ENUM
;
1016 return GL_INVALID_ENUM
;
1018 Update(feature_info
);
1020 UpdateCanRenderCondition();
1024 GLenum
Texture::SetParameterf(
1025 const FeatureInfo
* feature_info
, GLenum pname
, GLfloat param
) {
1027 case GL_TEXTURE_MIN_FILTER
:
1028 case GL_TEXTURE_MAG_FILTER
:
1029 case GL_TEXTURE_POOL_CHROMIUM
:
1030 case GL_TEXTURE_WRAP_R
:
1031 case GL_TEXTURE_WRAP_S
:
1032 case GL_TEXTURE_WRAP_T
:
1033 case GL_TEXTURE_COMPARE_FUNC
:
1034 case GL_TEXTURE_COMPARE_MODE
:
1035 case GL_TEXTURE_BASE_LEVEL
:
1036 case GL_TEXTURE_MAX_LEVEL
:
1037 case GL_TEXTURE_USAGE_ANGLE
:
1039 GLint iparam
= static_cast<GLint
>(param
);
1040 return SetParameteri(feature_info
, pname
, iparam
);
1042 case GL_TEXTURE_MIN_LOD
:
1045 case GL_TEXTURE_MAX_LOD
:
1048 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
1050 return GL_INVALID_VALUE
;
1055 return GL_INVALID_ENUM
;
1060 void Texture::Update(const FeatureInfo
* feature_info
) {
1061 // Update npot status.
1062 // Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others
1063 npot_
= (target_
== GL_TEXTURE_EXTERNAL_OES
) || (num_npot_faces_
> 0);
1065 if (face_infos_
.empty()) {
1066 texture_complete_
= false;
1067 cube_complete_
= false;
1071 // Update texture_complete and cube_complete status.
1072 const Texture::FaceInfo
& first_face
= face_infos_
[0];
1073 const Texture::LevelInfo
& first_level
= first_face
.level_infos
[0];
1074 const GLsizei levels_needed
= first_face
.num_mip_levels
;
1077 max_level_set_
>= (levels_needed
- 1) && max_level_set_
>= 0;
1078 cube_complete_
= (face_infos_
.size() == 6) &&
1079 (first_level
.width
== first_level
.height
);
1081 if (first_level
.width
== 0 || first_level
.height
== 0) {
1082 texture_complete_
= false;
1083 } else if (first_level
.type
== GL_FLOAT
&&
1084 !feature_info
->feature_flags().enable_texture_float_linear
&&
1085 (min_filter_
!= GL_NEAREST_MIPMAP_NEAREST
||
1086 mag_filter_
!= GL_NEAREST
)) {
1087 texture_complete_
= false;
1088 } else if (first_level
.type
== GL_HALF_FLOAT_OES
&&
1089 !feature_info
->feature_flags().enable_texture_half_float_linear
&&
1090 (min_filter_
!= GL_NEAREST_MIPMAP_NEAREST
||
1091 mag_filter_
!= GL_NEAREST
)) {
1092 texture_complete_
= false;
1095 if (cube_complete_
&& texture_level0_dirty_
) {
1096 texture_level0_complete_
= true;
1097 for (size_t ii
= 0; ii
< face_infos_
.size(); ++ii
) {
1098 const Texture::LevelInfo
& level0
= face_infos_
[ii
].level_infos
[0];
1099 if (!TextureFaceComplete(first_level
,
1102 level0
.internal_format
,
1108 texture_level0_complete_
= false;
1112 texture_level0_dirty_
= false;
1114 cube_complete_
&= texture_level0_complete_
;
1116 if (texture_complete_
&& texture_mips_dirty_
) {
1117 texture_mips_complete_
= true;
1119 ii
< face_infos_
.size() && texture_mips_complete_
;
1121 const Texture::FaceInfo
& face_info
= face_infos_
[ii
];
1122 const Texture::LevelInfo
& level0
= face_info
.level_infos
[0];
1123 for (GLsizei jj
= 1; jj
< levels_needed
; ++jj
) {
1124 const Texture::LevelInfo
& level_info
= face_infos_
[ii
].level_infos
[jj
];
1125 if (!TextureMipComplete(level0
,
1128 level_info
.internal_format
,
1134 texture_mips_complete_
= false;
1139 texture_mips_dirty_
= false;
1141 texture_complete_
&= texture_mips_complete_
;
1144 bool Texture::ClearRenderableLevels(GLES2Decoder
* decoder
) {
1150 for (size_t ii
= 0; ii
< face_infos_
.size(); ++ii
) {
1151 const Texture::FaceInfo
& face_info
= face_infos_
[ii
];
1152 for (GLint jj
= 0; jj
< face_info
.num_mip_levels
; ++jj
) {
1153 const Texture::LevelInfo
& info
= face_info
.level_infos
[jj
];
1154 if (info
.target
!= 0) {
1155 if (!ClearLevel(decoder
, info
.target
, jj
)) {
1161 UpdateSafeToRenderFrom(true);
1165 gfx::Rect
Texture::GetLevelClearedRect(GLenum target
, GLint level
) const {
1166 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
1167 if (face_index
>= face_infos_
.size() ||
1168 level
>= static_cast<GLint
>(face_infos_
[face_index
].level_infos
.size())) {
1172 const Texture::LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
1174 return info
.cleared_rect
;
1177 bool Texture::IsLevelCleared(GLenum target
, GLint level
) const {
1178 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
1179 if (face_index
>= face_infos_
.size() ||
1180 level
>= static_cast<GLint
>(face_infos_
[face_index
].level_infos
.size())) {
1184 const Texture::LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
1186 return info
.cleared_rect
== gfx::Rect(info
.width
, info
.height
);
1189 void Texture::InitTextureMaxAnisotropyIfNeeded(GLenum target
) {
1190 if (texture_max_anisotropy_initialized_
)
1192 texture_max_anisotropy_initialized_
= true;
1193 GLfloat params
[] = { 1.0f
};
1194 glTexParameterfv(target
, GL_TEXTURE_MAX_ANISOTROPY_EXT
, params
);
1197 bool Texture::ClearLevel(
1198 GLES2Decoder
* decoder
, GLenum target
, GLint level
) {
1200 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
1201 if (face_index
>= face_infos_
.size() ||
1202 level
>= static_cast<GLint
>(face_infos_
[face_index
].level_infos
.size())) {
1206 Texture::LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
1208 DCHECK(target
== info
.target
);
1210 if (info
.target
== 0 ||
1211 info
.cleared_rect
== gfx::Rect(info
.width
, info
.height
) ||
1212 info
.width
== 0 || info
.height
== 0 || info
.depth
== 0) {
1216 // Clear all remaining sub regions.
1218 0, info
.cleared_rect
.x(), info
.cleared_rect
.right(), info
.width
};
1220 0, info
.cleared_rect
.y(), info
.cleared_rect
.bottom(), info
.height
};
1222 for (size_t j
= 0; j
< 3; ++j
) {
1223 for (size_t i
= 0; i
< 3; ++i
) {
1224 // Center of nine patch is already cleared.
1225 if (j
== 1 && i
== 1)
1228 gfx::Rect
rect(x
[i
], y
[j
], x
[i
+ 1] - x
[i
], y
[j
+ 1] - y
[j
]);
1232 // NOTE: It seems kind of gross to call back into the decoder for this
1233 // but only the decoder knows all the state (like unpack_alignment_)
1234 // that's needed to be able to call GL correctly.
1235 bool cleared
= decoder
->ClearLevel(this, info
.target
, info
.level
,
1236 info
.format
, info
.type
, rect
.x(),
1237 rect
.y(), rect
.width(), rect
.height());
1243 UpdateMipCleared(&info
, info
.width
, info
.height
,
1244 gfx::Rect(info
.width
, info
.height
));
1248 void Texture::SetLevelImage(
1249 const FeatureInfo
* feature_info
,
1252 gfx::GLImage
* image
) {
1253 DCHECK_GE(level
, 0);
1254 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
1255 DCHECK_LT(static_cast<size_t>(face_index
),
1256 face_infos_
.size());
1257 DCHECK_LT(static_cast<size_t>(level
),
1258 face_infos_
[face_index
].level_infos
.size());
1259 Texture::LevelInfo
& info
=
1260 face_infos_
[face_index
].level_infos
[level
];
1261 DCHECK_EQ(info
.target
, target
);
1262 DCHECK_EQ(info
.level
, level
);
1264 UpdateCanRenderCondition();
1268 gfx::GLImage
* Texture::GetLevelImage(GLint target
, GLint level
) const {
1269 if (target
!= GL_TEXTURE_2D
&& target
!= GL_TEXTURE_EXTERNAL_OES
&&
1270 target
!= GL_TEXTURE_RECTANGLE_ARB
) {
1274 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
1275 if (level
>= 0 && face_index
< face_infos_
.size() &&
1276 static_cast<size_t>(level
) < face_infos_
[face_index
].level_infos
.size()) {
1277 const LevelInfo
& info
= face_infos_
[face_index
].level_infos
[level
];
1278 if (info
.target
!= 0) {
1279 return info
.image
.get();
1285 void Texture::OnWillModifyPixels() {
1286 gfx::GLImage
* image
= GetLevelImage(target(), 0);
1288 image
->WillModifyTexImage();
1291 void Texture::OnDidModifyPixels() {
1292 gfx::GLImage
* image
= GetLevelImage(target(), 0);
1294 image
->DidModifyTexImage();
1297 TextureRef::TextureRef(TextureManager
* manager
,
1300 : manager_(manager
),
1302 client_id_(client_id
),
1306 texture_
->AddTextureRef(this);
1307 manager_
->StartTracking(this);
1310 scoped_refptr
<TextureRef
> TextureRef::Create(TextureManager
* manager
,
1312 GLuint service_id
) {
1313 return new TextureRef(manager
, client_id
, new Texture(service_id
));
1316 TextureRef::~TextureRef() {
1317 manager_
->StopTracking(this);
1318 texture_
->RemoveTextureRef(this, manager_
->have_context_
);
1322 TextureManager::TextureManager(MemoryTracker
* memory_tracker
,
1323 FeatureInfo
* feature_info
,
1324 GLint max_texture_size
,
1325 GLint max_cube_map_texture_size
,
1326 GLint max_rectangle_texture_size
,
1327 GLint max_3d_texture_size
,
1328 bool use_default_textures
)
1329 : memory_tracker_managed_(
1330 new MemoryTypeTracker(memory_tracker
, MemoryTracker::kManaged
)),
1331 memory_tracker_unmanaged_(
1332 new MemoryTypeTracker(memory_tracker
, MemoryTracker::kUnmanaged
)),
1333 memory_tracker_(memory_tracker
),
1334 feature_info_(feature_info
),
1335 framebuffer_manager_(NULL
),
1336 max_texture_size_(max_texture_size
),
1337 max_cube_map_texture_size_(max_cube_map_texture_size
),
1338 max_rectangle_texture_size_(max_rectangle_texture_size
),
1339 max_3d_texture_size_(max_3d_texture_size
),
1340 max_levels_(ComputeMipMapCount(GL_TEXTURE_2D
,
1344 max_cube_map_levels_(ComputeMipMapCount(GL_TEXTURE_CUBE_MAP
,
1345 max_cube_map_texture_size
,
1346 max_cube_map_texture_size
,
1347 max_cube_map_texture_size
)),
1348 max_3d_levels_(ComputeMipMapCount(GL_TEXTURE_3D
,
1349 // Same as GL_TEXTURE_2D_ARRAY
1350 max_3d_texture_size
,
1351 max_3d_texture_size
,
1352 max_3d_texture_size
)),
1353 use_default_textures_(use_default_textures
),
1354 num_unrenderable_textures_(0),
1355 num_unsafe_textures_(0),
1356 num_uncleared_mips_(0),
1359 have_context_(true) {
1360 for (int ii
= 0; ii
< kNumDefaultTextures
; ++ii
) {
1361 black_texture_ids_
[ii
] = 0;
1365 bool TextureManager::Initialize() {
1366 // TODO(gman): The default textures have to be real textures, not the 0
1367 // texture because we simulate non shared resources on top of shared
1368 // resources and all contexts that share resource share the same default
1370 default_textures_
[kTexture2D
] = CreateDefaultAndBlackTextures(
1371 GL_TEXTURE_2D
, &black_texture_ids_
[kTexture2D
]);
1372 default_textures_
[kCubeMap
] = CreateDefaultAndBlackTextures(
1373 GL_TEXTURE_CUBE_MAP
, &black_texture_ids_
[kCubeMap
]);
1375 if (feature_info_
->feature_flags().oes_egl_image_external
) {
1376 default_textures_
[kExternalOES
] = CreateDefaultAndBlackTextures(
1377 GL_TEXTURE_EXTERNAL_OES
, &black_texture_ids_
[kExternalOES
]);
1380 if (feature_info_
->feature_flags().arb_texture_rectangle
) {
1381 default_textures_
[kRectangleARB
] = CreateDefaultAndBlackTextures(
1382 GL_TEXTURE_RECTANGLE_ARB
, &black_texture_ids_
[kRectangleARB
]);
1385 // When created from InProcessCommandBuffer, we won't have a |memory_tracker_|
1386 // so don't register a dump provider.
1387 if (memory_tracker_
) {
1388 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
1389 this, base::ThreadTaskRunnerHandle::Get());
1395 scoped_refptr
<TextureRef
>
1396 TextureManager::CreateDefaultAndBlackTextures(
1398 GLuint
* black_texture
) {
1399 static uint8 black
[] = {0, 0, 0, 255};
1401 // Sampling a texture not associated with any EGLImage sibling will return
1402 // black values according to the spec.
1403 bool needs_initialization
= (target
!= GL_TEXTURE_EXTERNAL_OES
);
1404 bool needs_faces
= (target
== GL_TEXTURE_CUBE_MAP
);
1406 // Make default textures and texture for replacing non-renderable textures.
1408 const int num_ids
= use_default_textures_
? 2 : 1;
1409 glGenTextures(num_ids
, ids
);
1410 for (int ii
= 0; ii
< num_ids
; ++ii
) {
1411 glBindTexture(target
, ids
[ii
]);
1412 if (needs_initialization
) {
1414 for (int jj
= 0; jj
< GLES2Util::kNumFaces
; ++jj
) {
1415 glTexImage2D(GLES2Util::IndexToGLFaceTarget(jj
), 0, GL_RGBA
, 1, 1, 0,
1416 GL_RGBA
, GL_UNSIGNED_BYTE
, black
);
1419 glTexImage2D(target
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
,
1420 GL_UNSIGNED_BYTE
, black
);
1424 glBindTexture(target
, 0);
1426 scoped_refptr
<TextureRef
> default_texture
;
1427 if (use_default_textures_
) {
1428 default_texture
= TextureRef::Create(this, 0, ids
[1]);
1429 SetTarget(default_texture
.get(), target
);
1431 for (int ii
= 0; ii
< GLES2Util::kNumFaces
; ++ii
) {
1432 SetLevelInfo(default_texture
.get(), GLES2Util::IndexToGLFaceTarget(ii
),
1433 0, GL_RGBA
, 1, 1, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
,
1437 if (needs_initialization
) {
1438 SetLevelInfo(default_texture
.get(), GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 1,
1439 0, GL_RGBA
, GL_UNSIGNED_BYTE
, gfx::Rect(1, 1));
1441 SetLevelInfo(default_texture
.get(), GL_TEXTURE_EXTERNAL_OES
, 0, GL_RGBA
,
1442 1, 1, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, gfx::Rect(1, 1));
1447 *black_texture
= ids
[0];
1448 return default_texture
;
1451 bool TextureManager::ValidForTarget(
1452 GLenum target
, GLint level
, GLsizei width
, GLsizei height
, GLsizei depth
) {
1453 GLsizei max_size
= MaxSizeForTarget(target
) >> level
;
1454 return level
>= 0 &&
1458 level
< MaxLevelsForTarget(target
) &&
1459 width
<= max_size
&&
1460 height
<= max_size
&&
1461 depth
<= max_size
&&
1462 (level
== 0 || feature_info_
->feature_flags().npot_ok
||
1463 (!GLES2Util::IsNPOT(width
) &&
1464 !GLES2Util::IsNPOT(height
) &&
1465 !GLES2Util::IsNPOT(depth
))) &&
1466 (target
!= GL_TEXTURE_CUBE_MAP
|| (width
== height
&& depth
== 1)) &&
1467 (target
!= GL_TEXTURE_2D
|| (depth
== 1));
1470 void TextureManager::SetTarget(TextureRef
* ref
, GLenum target
) {
1473 ->SetTarget(feature_info_
.get(), target
, MaxLevelsForTarget(target
));
1476 void TextureManager::SetLevelClearedRect(TextureRef
* ref
,
1479 const gfx::Rect
& cleared_rect
) {
1481 ref
->texture()->SetLevelClearedRect(target
, level
, cleared_rect
);
1484 void TextureManager::SetLevelCleared(TextureRef
* ref
,
1489 ref
->texture()->SetLevelCleared(target
, level
, cleared
);
1492 bool TextureManager::ClearRenderableLevels(
1493 GLES2Decoder
* decoder
, TextureRef
* ref
) {
1495 return ref
->texture()->ClearRenderableLevels(decoder
);
1498 bool TextureManager::ClearTextureLevel(
1499 GLES2Decoder
* decoder
, TextureRef
* ref
,
1500 GLenum target
, GLint level
) {
1502 Texture
* texture
= ref
->texture();
1503 if (texture
->num_uncleared_mips() == 0) {
1506 bool result
= texture
->ClearLevel(decoder
, target
, level
);
1507 texture
->UpdateCleared();
1511 void TextureManager::SetLevelInfo(TextureRef
* ref
,
1514 GLenum internal_format
,
1521 const gfx::Rect
& cleared_rect
) {
1522 DCHECK(gfx::Rect(width
, height
).Contains(cleared_rect
));
1524 Texture
* texture
= ref
->texture();
1526 texture
->GetMemTracker()->TrackMemFree(texture
->estimated_size());
1527 texture
->SetLevelInfo(feature_info_
.get(), target
, level
, internal_format
,
1528 width
, height
, depth
, border
, format
, type
,
1530 texture
->GetMemTracker()->TrackMemAlloc(texture
->estimated_size());
1533 Texture
* TextureManager::Produce(TextureRef
* ref
) {
1535 return ref
->texture();
1538 TextureRef
* TextureManager::Consume(
1542 scoped_refptr
<TextureRef
> ref(new TextureRef(this, client_id
, texture
));
1543 bool result
= textures_
.insert(std::make_pair(client_id
, ref
)).second
;
1548 void TextureManager::SetParameteri(
1549 const char* function_name
, ErrorState
* error_state
,
1550 TextureRef
* ref
, GLenum pname
, GLint param
) {
1551 DCHECK(error_state
);
1553 Texture
* texture
= ref
->texture();
1554 GLenum result
= texture
->SetParameteri(feature_info_
.get(), pname
, param
);
1555 if (result
!= GL_NO_ERROR
) {
1556 if (result
== GL_INVALID_ENUM
) {
1557 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1558 error_state
, function_name
, param
, "param");
1560 ERRORSTATE_SET_GL_ERROR_INVALID_PARAMI(
1561 error_state
, result
, function_name
, pname
, param
);
1564 // Texture tracking pools exist only for the command decoder, so
1565 // do not pass them on to the native GL implementation.
1566 if (pname
!= GL_TEXTURE_POOL_CHROMIUM
) {
1567 glTexParameteri(texture
->target(), pname
, param
);
1572 void TextureManager::SetParameterf(
1573 const char* function_name
, ErrorState
* error_state
,
1574 TextureRef
* ref
, GLenum pname
, GLfloat param
) {
1575 DCHECK(error_state
);
1577 Texture
* texture
= ref
->texture();
1578 GLenum result
= texture
->SetParameterf(feature_info_
.get(), pname
, param
);
1579 if (result
!= GL_NO_ERROR
) {
1580 if (result
== GL_INVALID_ENUM
) {
1581 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1582 error_state
, function_name
, pname
, "pname");
1584 ERRORSTATE_SET_GL_ERROR_INVALID_PARAMF(
1585 error_state
, result
, function_name
, pname
, param
);
1588 // Texture tracking pools exist only for the command decoder, so
1589 // do not pass them on to the native GL implementation.
1590 if (pname
!= GL_TEXTURE_POOL_CHROMIUM
) {
1591 glTexParameterf(texture
->target(), pname
, param
);
1596 bool TextureManager::MarkMipmapsGenerated(TextureRef
* ref
) {
1598 Texture
* texture
= ref
->texture();
1599 texture
->GetMemTracker()->TrackMemFree(texture
->estimated_size());
1600 bool result
= texture
->MarkMipmapsGenerated(feature_info_
.get());
1601 texture
->GetMemTracker()->TrackMemAlloc(texture
->estimated_size());
1605 TextureRef
* TextureManager::CreateTexture(
1606 GLuint client_id
, GLuint service_id
) {
1607 DCHECK_NE(0u, service_id
);
1608 scoped_refptr
<TextureRef
> ref(TextureRef::Create(
1609 this, client_id
, service_id
));
1610 std::pair
<TextureMap::iterator
, bool> result
=
1611 textures_
.insert(std::make_pair(client_id
, ref
));
1612 DCHECK(result
.second
);
1616 TextureRef
* TextureManager::GetTexture(
1617 GLuint client_id
) const {
1618 TextureMap::const_iterator it
= textures_
.find(client_id
);
1619 return it
!= textures_
.end() ? it
->second
.get() : NULL
;
1622 void TextureManager::RemoveTexture(GLuint client_id
) {
1623 TextureMap::iterator it
= textures_
.find(client_id
);
1624 if (it
!= textures_
.end()) {
1625 it
->second
->reset_client_id();
1626 textures_
.erase(it
);
1630 void TextureManager::StartTracking(TextureRef
* ref
) {
1631 Texture
* texture
= ref
->texture();
1633 num_uncleared_mips_
+= texture
->num_uncleared_mips();
1634 if (!texture
->SafeToRenderFrom())
1635 ++num_unsafe_textures_
;
1636 if (!texture
->CanRender(feature_info_
.get()))
1637 ++num_unrenderable_textures_
;
1638 if (texture
->HasImages())
1642 void TextureManager::StopTracking(TextureRef
* ref
) {
1643 if (ref
->num_observers()) {
1644 for (unsigned int i
= 0; i
< destruction_observers_
.size(); i
++) {
1645 destruction_observers_
[i
]->OnTextureRefDestroying(ref
);
1647 DCHECK_EQ(ref
->num_observers(), 0);
1650 Texture
* texture
= ref
->texture();
1653 if (texture
->HasImages()) {
1654 DCHECK_NE(0, num_images_
);
1657 if (!texture
->CanRender(feature_info_
.get())) {
1658 DCHECK_NE(0, num_unrenderable_textures_
);
1659 --num_unrenderable_textures_
;
1661 if (!texture
->SafeToRenderFrom()) {
1662 DCHECK_NE(0, num_unsafe_textures_
);
1663 --num_unsafe_textures_
;
1665 num_uncleared_mips_
-= texture
->num_uncleared_mips();
1666 DCHECK_GE(num_uncleared_mips_
, 0);
1669 MemoryTypeTracker
* TextureManager::GetMemTracker(GLenum tracking_pool
) {
1670 switch (tracking_pool
) {
1671 case GL_TEXTURE_POOL_MANAGED_CHROMIUM
:
1672 return memory_tracker_managed_
.get();
1674 case GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
:
1675 return memory_tracker_unmanaged_
.get();
1684 Texture
* TextureManager::GetTextureForServiceId(GLuint service_id
) const {
1685 // This doesn't need to be fast. It's only used during slow queries.
1686 for (TextureMap::const_iterator it
= textures_
.begin();
1687 it
!= textures_
.end(); ++it
) {
1688 Texture
* texture
= it
->second
->texture();
1689 if (texture
->service_id() == service_id
)
1695 GLsizei
TextureManager::ComputeMipMapCount(GLenum target
,
1700 case GL_TEXTURE_EXTERNAL_OES
:
1704 base::bits::Log2Floor(std::max(std::max(width
, height
), depth
));
1708 void TextureManager::SetLevelImage(
1712 gfx::GLImage
* image
) {
1714 ref
->texture()->SetLevelImage(feature_info_
.get(), target
, level
, image
);
1717 size_t TextureManager::GetSignatureSize() const {
1718 return sizeof(TextureTag
) + sizeof(TextureSignature
);
1721 void TextureManager::AddToSignature(
1725 std::string
* signature
) const {
1726 ref
->texture()->AddToSignature(feature_info_
.get(), target
, level
, signature
);
1729 void TextureManager::UpdateSafeToRenderFrom(int delta
) {
1730 num_unsafe_textures_
+= delta
;
1731 DCHECK_GE(num_unsafe_textures_
, 0);
1734 void TextureManager::UpdateUnclearedMips(int delta
) {
1735 num_uncleared_mips_
+= delta
;
1736 DCHECK_GE(num_uncleared_mips_
, 0);
1739 void TextureManager::UpdateCanRenderCondition(
1740 Texture::CanRenderCondition old_condition
,
1741 Texture::CanRenderCondition new_condition
) {
1742 if (old_condition
== Texture::CAN_RENDER_NEVER
||
1743 (old_condition
== Texture::CAN_RENDER_ONLY_IF_NPOT
&&
1744 !feature_info_
->feature_flags().npot_ok
)) {
1745 DCHECK_GT(num_unrenderable_textures_
, 0);
1746 --num_unrenderable_textures_
;
1748 if (new_condition
== Texture::CAN_RENDER_NEVER
||
1749 (new_condition
== Texture::CAN_RENDER_ONLY_IF_NPOT
&&
1750 !feature_info_
->feature_flags().npot_ok
))
1751 ++num_unrenderable_textures_
;
1754 void TextureManager::UpdateNumImages(int delta
) {
1755 num_images_
+= delta
;
1756 DCHECK_GE(num_images_
, 0);
1759 void TextureManager::IncFramebufferStateChangeCount() {
1760 if (framebuffer_manager_
)
1761 framebuffer_manager_
->IncFramebufferStateChangeCount();
1764 bool TextureManager::ValidateFormatAndTypeCombination(
1765 ErrorState
* error_state
, const char* function_name
, GLenum format
,
1767 // TODO(zmo): now this is only called by GLES2DecoderImpl::DoCopyTexImage2D
1768 // and is incorrect for ES3. Fix this.
1769 if (!g_format_type_validator
.Get().IsValid(format
, format
, type
)) {
1770 ERRORSTATE_SET_GL_ERROR(
1771 error_state
, GL_INVALID_OPERATION
, function_name
,
1772 (std::string("invalid type ") +
1773 GLES2Util::GetStringEnum(type
) + " for format " +
1774 GLES2Util::GetStringEnum(format
)).c_str());
1780 bool TextureManager::ValidateTextureParameters(
1781 ErrorState
* error_state
, const char* function_name
,
1782 GLenum format
, GLenum type
, GLenum internal_format
, GLint level
) {
1783 const Validators
* validators
= feature_info_
->validators();
1784 if (!validators
->texture_format
.IsValid(format
)) {
1785 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1786 error_state
, function_name
, format
, "format");
1789 if (!validators
->pixel_type
.IsValid(type
)) {
1790 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1791 error_state
, function_name
, type
, "type");
1794 if (!g_format_type_validator
.Get().IsValid(internal_format
, format
, type
)) {
1795 ERRORSTATE_SET_GL_ERROR(
1796 error_state
, GL_INVALID_OPERATION
, function_name
,
1797 "invalid internalformat/format/type combination");
1800 // For TexSubImage calls, internal_format isn't part of the parameters,
1801 // so its validation needs to be after the internal_format/format/type
1802 // combination validation. Otherwise, an unexpected INVALID_ENUM could be
1803 // generated instead of INVALID_OPERATION.
1804 if (!validators
->texture_internal_format
.IsValid(internal_format
)) {
1805 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1806 error_state
, function_name
, internal_format
, "internal_format");
1809 if (!feature_info_
->IsES3Enabled()) {
1810 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
1811 if ((channels
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0 && level
) {
1812 ERRORSTATE_SET_GL_ERROR(
1813 error_state
, GL_INVALID_OPERATION
, function_name
,
1814 (std::string("invalid format ") + GLES2Util::GetStringEnum(format
) +
1815 " for level != 0").c_str());
1822 // Gets the texture id for a given target.
1823 TextureRef
* TextureManager::GetTextureInfoForTarget(
1824 ContextState
* state
, GLenum target
) {
1825 TextureUnit
& unit
= state
->texture_units
[state
->active_texture_unit
];
1826 TextureRef
* texture
= NULL
;
1829 texture
= unit
.bound_texture_2d
.get();
1831 case GL_TEXTURE_CUBE_MAP
:
1832 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
1833 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
1834 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
1835 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
1836 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
1837 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
1838 texture
= unit
.bound_texture_cube_map
.get();
1840 case GL_TEXTURE_EXTERNAL_OES
:
1841 texture
= unit
.bound_texture_external_oes
.get();
1843 case GL_TEXTURE_RECTANGLE_ARB
:
1844 texture
= unit
.bound_texture_rectangle_arb
.get();
1847 texture
= unit
.bound_texture_3d
.get();
1849 case GL_TEXTURE_2D_ARRAY
:
1850 texture
= unit
.bound_texture_2d_array
.get();
1859 TextureRef
* TextureManager::GetTextureInfoForTargetUnlessDefault(
1860 ContextState
* state
, GLenum target
) {
1861 TextureRef
* texture
= GetTextureInfoForTarget(state
, target
);
1864 if (texture
== GetDefaultTextureInfo(target
))
1869 bool TextureManager::ValidateTexImage(
1870 ContextState
* state
,
1871 const char* function_name
,
1872 const DoTexImageArguments
& args
,
1873 TextureRef
** texture_ref
) {
1874 ErrorState
* error_state
= state
->GetErrorState();
1875 const Validators
* validators
= feature_info_
->validators();
1876 if (((args
.command_type
== DoTexImageArguments::kTexImage2D
) &&
1877 !validators
->texture_target
.IsValid(args
.target
)) ||
1878 ((args
.command_type
== DoTexImageArguments::kTexImage3D
) &&
1879 !validators
->texture_3_d_target
.IsValid(args
.target
))) {
1880 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1881 error_state
, function_name
, args
.target
, "target");
1884 if (!ValidateTextureParameters(
1885 error_state
, function_name
, args
.format
, args
.type
,
1886 args
.internal_format
, args
.level
)) {
1889 if (!ValidForTarget(args
.target
, args
.level
,
1890 args
.width
, args
.height
, args
.depth
) ||
1892 ERRORSTATE_SET_GL_ERROR(
1893 error_state
, GL_INVALID_VALUE
, function_name
,
1894 "dimensions out of range");
1897 if ((GLES2Util::GetChannelsForFormat(args
.format
) &
1898 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0 && args
.pixels
1899 && !feature_info_
->IsES3Enabled()) {
1900 ERRORSTATE_SET_GL_ERROR(
1901 error_state
, GL_INVALID_OPERATION
,
1902 function_name
, "can not supply data for depth or stencil textures");
1906 TextureRef
* local_texture_ref
= GetTextureInfoForTarget(state
, args
.target
);
1907 if (!local_texture_ref
) {
1908 ERRORSTATE_SET_GL_ERROR(
1909 error_state
, GL_INVALID_OPERATION
, function_name
,
1910 "unknown texture for target");
1913 if (local_texture_ref
->texture()->IsImmutable()) {
1914 ERRORSTATE_SET_GL_ERROR(
1915 error_state
, GL_INVALID_OPERATION
, function_name
,
1916 "texture is immutable");
1920 if (!memory_tracker_managed_
->EnsureGPUMemoryAvailable(args
.pixels_size
)) {
1921 ERRORSTATE_SET_GL_ERROR(error_state
, GL_OUT_OF_MEMORY
, function_name
,
1926 // Write the TextureReference since this is valid.
1927 *texture_ref
= local_texture_ref
;
1931 void TextureManager::ValidateAndDoTexImage(
1932 DecoderTextureState
* texture_state
,
1933 ContextState
* state
,
1934 DecoderFramebufferState
* framebuffer_state
,
1935 const char* function_name
,
1936 const DoTexImageArguments
& args
) {
1937 TextureRef
* texture_ref
;
1938 if (!ValidateTexImage(state
, function_name
, args
, &texture_ref
)) {
1942 DoTexImage(texture_state
, state
->GetErrorState(), framebuffer_state
,
1943 function_name
, texture_ref
, args
);
1946 GLenum
TextureManager::AdjustTexFormat(GLenum format
) const {
1947 // TODO(bajones): GLES 3 allows for internal format and format to differ.
1948 // This logic may need to change as a result.
1949 if (gfx::GetGLImplementation() == gfx::kGLImplementationDesktopGL
) {
1950 if (format
== GL_SRGB_EXT
)
1952 if (format
== GL_SRGB_ALPHA_EXT
)
1958 void TextureManager::DoTexImage(
1959 DecoderTextureState
* texture_state
,
1960 ErrorState
* error_state
,
1961 DecoderFramebufferState
* framebuffer_state
,
1962 const char* function_name
,
1963 TextureRef
* texture_ref
,
1964 const DoTexImageArguments
& args
) {
1965 Texture
* texture
= texture_ref
->texture();
1966 GLsizei tex_width
= 0;
1967 GLsizei tex_height
= 0;
1968 GLsizei tex_depth
= 0;
1969 GLenum tex_type
= 0;
1970 GLenum tex_format
= 0;
1971 bool level_is_same
=
1972 texture
->GetLevelSize(
1973 args
.target
, args
.level
, &tex_width
, &tex_height
, &tex_depth
) &&
1974 texture
->GetLevelType(args
.target
, args
.level
, &tex_type
, &tex_format
) &&
1975 args
.width
== tex_width
&& args
.height
== tex_height
&&
1976 args
.depth
== tex_depth
&& args
.type
== tex_type
&&
1977 args
.format
== tex_format
;
1979 if (level_is_same
&& !args
.pixels
) {
1980 // Just set the level texture but mark the texture as uncleared.
1981 SetLevelInfo(texture_ref
, args
.target
, args
.level
, args
.internal_format
,
1982 args
.width
, args
.height
, args
.depth
, args
.border
, args
.format
,
1983 args
.type
, gfx::Rect());
1984 texture_state
->tex_image_failed
= false;
1988 if (texture
->IsAttachedToFramebuffer()) {
1989 framebuffer_state
->clear_state_dirty
= true;
1992 if (texture_state
->texsubimage_faster_than_teximage
&&
1993 level_is_same
&& args
.pixels
) {
1995 ScopedTextureUploadTimer
timer(texture_state
);
1996 if (args
.command_type
== DoTexImageArguments::kTexImage3D
) {
1997 glTexSubImage3D(args
.target
, args
.level
, 0, 0, 0,
1998 args
.width
, args
.height
, args
.depth
,
1999 args
.format
, args
.type
, args
.pixels
);
2001 glTexSubImage2D(args
.target
, args
.level
, 0, 0, args
.width
, args
.height
,
2002 AdjustTexFormat(args
.format
), args
.type
, args
.pixels
);
2005 SetLevelCleared(texture_ref
, args
.target
, args
.level
, true);
2006 texture_state
->tex_image_failed
= false;
2010 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state
, function_name
);
2012 ScopedTextureUploadTimer
timer(texture_state
);
2013 if (args
.command_type
== DoTexImageArguments::kTexImage3D
) {
2014 glTexImage3D(args
.target
, args
.level
, args
.internal_format
, args
.width
,
2015 args
.height
, args
.depth
, args
.border
, args
.format
,
2016 args
.type
, args
.pixels
);
2018 glTexImage2D(args
.target
, args
.level
, args
.internal_format
, args
.width
,
2019 args
.height
, args
.border
, AdjustTexFormat(args
.format
),
2020 args
.type
, args
.pixels
);
2023 GLenum error
= ERRORSTATE_PEEK_GL_ERROR(error_state
, function_name
);
2024 if (error
== GL_NO_ERROR
) {
2026 texture_ref
, args
.target
, args
.level
, args
.internal_format
, args
.width
,
2027 args
.height
, args
.depth
, args
.border
, args
.format
, args
.type
,
2028 args
.pixels
!= NULL
? gfx::Rect(args
.width
, args
.height
) : gfx::Rect());
2029 texture_state
->tex_image_failed
= false;
2033 ScopedTextureUploadTimer::ScopedTextureUploadTimer(
2034 DecoderTextureState
* texture_state
)
2035 : texture_state_(texture_state
),
2036 begin_time_(base::TimeTicks::Now()) {
2039 ScopedTextureUploadTimer::~ScopedTextureUploadTimer() {
2040 texture_state_
->texture_upload_count
++;
2041 texture_state_
->total_texture_upload_time
+=
2042 base::TimeTicks::Now() - begin_time_
;
2045 bool TextureManager::OnMemoryDump(const base::trace_event::MemoryDumpArgs
& args
,
2046 base::trace_event::ProcessMemoryDump
* pmd
) {
2047 for (const auto& resource
: textures_
) {
2048 // Only dump memory info for textures actually owned by this TextureManager.
2049 DumpTextureRef(pmd
, resource
.second
.get());
2052 // Also dump TextureManager internal textures, if allocated.
2053 for (int i
= 0; i
< kNumDefaultTextures
; i
++) {
2054 if (default_textures_
[i
]) {
2055 DumpTextureRef(pmd
, default_textures_
[i
].get());
2062 void TextureManager::DumpTextureRef(base::trace_event::ProcessMemoryDump
* pmd
,
2064 // TODO(ericrk): Trace image-backed textures. crbug.com/514914
2065 if (ref
->texture()->HasImages())
2068 uint32_t size
= ref
->texture()->estimated_size();
2070 // Ignore unallocated texture IDs.
2074 std::string dump_name
=
2075 base::StringPrintf("gl/textures/client_%d/texture_%d",
2076 memory_tracker_
->ClientId(), ref
->client_id());
2077 base::trace_event::MemoryAllocatorDump
* dump
=
2078 pmd
->CreateAllocatorDump(dump_name
);
2079 dump
->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize
,
2080 base::trace_event::MemoryAllocatorDump::kUnitsBytes
,
2081 static_cast<uint64_t>(size
));
2083 // Add the |client_guid| which expresses shared ownership with the client
2085 auto client_guid
= gfx::GetGLTextureGUIDForTracing(
2086 memory_tracker_
->ClientTracingId(), ref
->client_id());
2087 pmd
->CreateSharedGlobalAllocatorDump(client_guid
);
2088 pmd
->AddOwnershipEdge(dump
->guid(), client_guid
);
2090 // Add a |service_guid| which expresses shared ownership between the various
2092 // TODO(ericrk): May need to ensure uniqueness using GLShareGroup and
2093 // potentially cross-share-group sharing via EGLImages. crbug.com/512534
2095 gfx::GetGLTextureGUIDForTracing(0, ref
->texture()->service_id());
2096 pmd
->CreateSharedGlobalAllocatorDump(service_guid
);
2098 int importance
= 0; // Default importance.
2099 // The link to the memory tracking |client_id| is given a higher importance
2101 if (ref
== ref
->texture()->memory_tracking_ref_
)
2104 pmd
->AddOwnershipEdge(client_guid
, service_guid
, importance
);
2107 } // namespace gles2