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"
10 #include "base/bits.h"
11 #include "base/strings/stringprintf.h"
12 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
13 #include "gpu/command_buffer/service/context_state.h"
14 #include "gpu/command_buffer/service/error_state.h"
15 #include "gpu/command_buffer/service/feature_info.h"
16 #include "gpu/command_buffer/service/framebuffer_manager.h"
17 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
18 #include "gpu/command_buffer/service/mailbox_manager.h"
19 #include "gpu/command_buffer/service/memory_tracking.h"
24 TextureManager::DestructionObserver::DestructionObserver() {}
26 TextureManager::DestructionObserver::~DestructionObserver() {}
28 TextureManager::~TextureManager() {
29 for (unsigned int i
= 0; i
< destruction_observers_
.size(); i
++)
30 destruction_observers_
[i
]->OnTextureManagerDestroying(this);
32 DCHECK(textures_
.empty());
34 // If this triggers, that means something is keeping a reference to
35 // a Texture belonging to this.
36 CHECK_EQ(texture_count_
, 0u);
38 DCHECK_EQ(0, num_unrenderable_textures_
);
39 DCHECK_EQ(0, num_unsafe_textures_
);
40 DCHECK_EQ(0, num_uncleared_mips_
);
41 DCHECK_EQ(0, num_images_
);
44 void TextureManager::Destroy(bool have_context
) {
45 have_context_
= have_context
;
47 for (int ii
= 0; ii
< kNumDefaultTextures
; ++ii
) {
48 default_textures_
[ii
] = NULL
;
52 glDeleteTextures(arraysize(black_texture_ids_
), black_texture_ids_
);
55 DCHECK_EQ(0u, memory_tracker_managed_
->GetMemRepresented());
56 DCHECK_EQ(0u, memory_tracker_unmanaged_
->GetMemRepresented());
59 Texture::Texture(GLuint service_id
)
60 : mailbox_manager_(NULL
),
61 memory_tracking_ref_(NULL
),
62 service_id_(service_id
),
64 num_uncleared_mips_(0),
66 min_filter_(GL_NEAREST_MIPMAP_LINEAR
),
67 mag_filter_(GL_LINEAR
),
71 pool_(GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
),
73 texture_complete_(false),
74 cube_complete_(false),
76 has_been_bound_(false),
77 framebuffer_attachment_count_(0),
81 can_render_condition_(CAN_RENDER_ALWAYS
),
82 texture_max_anisotropy_initialized_(false) {
87 mailbox_manager_
->TextureDeleted(this);
90 void Texture::AddTextureRef(TextureRef
* ref
) {
91 DCHECK(refs_
.find(ref
) == refs_
.end());
93 if (!memory_tracking_ref_
) {
94 memory_tracking_ref_
= ref
;
95 GetMemTracker()->TrackMemAlloc(estimated_size());
99 void Texture::RemoveTextureRef(TextureRef
* ref
, bool have_context
) {
100 if (memory_tracking_ref_
== ref
) {
101 GetMemTracker()->TrackMemFree(estimated_size());
102 memory_tracking_ref_
= NULL
;
104 size_t result
= refs_
.erase(ref
);
105 DCHECK_EQ(result
, 1u);
108 GLuint id
= service_id();
109 glDeleteTextures(1, &id
);
112 } else if (memory_tracking_ref_
== NULL
) {
113 // TODO(piman): tune ownership semantics for cross-context group shared
115 memory_tracking_ref_
= *refs_
.begin();
116 GetMemTracker()->TrackMemAlloc(estimated_size());
120 MemoryTypeTracker
* Texture::GetMemTracker() {
121 DCHECK(memory_tracking_ref_
);
122 return memory_tracking_ref_
->manager()->GetMemTracker(pool_
);
125 Texture::LevelInfo::LevelInfo()
139 Texture::LevelInfo::LevelInfo(const LevelInfo
& rhs
)
140 : cleared(rhs
.cleared
),
143 internal_format(rhs
.internal_format
),
151 estimated_size(rhs
.estimated_size
) {
154 Texture::LevelInfo::~LevelInfo() {
157 Texture::CanRenderCondition
Texture::GetCanRenderCondition() const {
159 return CAN_RENDER_ALWAYS
;
161 if (target_
!= GL_TEXTURE_EXTERNAL_OES
) {
162 if (level_infos_
.empty()) {
163 return CAN_RENDER_NEVER
;
166 const Texture::LevelInfo
& first_face
= level_infos_
[0][0];
167 if (first_face
.width
== 0 ||
168 first_face
.height
== 0 ||
169 first_face
.depth
== 0) {
170 return CAN_RENDER_NEVER
;
174 bool needs_mips
= NeedsMips();
176 if (!texture_complete())
177 return CAN_RENDER_NEVER
;
178 if (target_
== GL_TEXTURE_CUBE_MAP
&& !cube_complete())
179 return CAN_RENDER_NEVER
;
182 bool is_npot_compatible
= !needs_mips
&&
183 wrap_s_
== GL_CLAMP_TO_EDGE
&&
184 wrap_t_
== GL_CLAMP_TO_EDGE
;
186 if (!is_npot_compatible
) {
187 if (target_
== GL_TEXTURE_RECTANGLE_ARB
)
188 return CAN_RENDER_NEVER
;
190 return CAN_RENDER_ONLY_IF_NPOT
;
193 return CAN_RENDER_ALWAYS
;
196 bool Texture::CanRender(const FeatureInfo
* feature_info
) const {
197 switch (can_render_condition_
) {
198 case CAN_RENDER_ALWAYS
:
200 case CAN_RENDER_NEVER
:
202 case CAN_RENDER_ONLY_IF_NPOT
:
205 return feature_info
->feature_flags().npot_ok
;
208 void Texture::AddToSignature(
209 const FeatureInfo
* feature_info
,
212 std::string
* signature
) const {
213 DCHECK(feature_info
);
216 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
217 DCHECK_LT(static_cast<size_t>(face_index
),
218 level_infos_
.size());
219 DCHECK_LT(static_cast<size_t>(level
),
220 level_infos_
[face_index
].size());
221 const Texture::LevelInfo
& info
=
222 level_infos_
[face_index
][level
];
223 *signature
+= base::StringPrintf(
224 "|Texture|target=%04x|level=%d|internal_format=%04x"
225 "|width=%d|height=%d|depth=%d|border=%d|format=%04x|type=%04x"
226 "|image=%d|canrender=%d|canrenderto=%d|npot_=%d"
227 "|min_filter=%04x|mag_filter=%04x|wrap_s=%04x|wrap_t=%04x"
229 target
, level
, info
.internal_format
,
230 info
.width
, info
.height
, info
.depth
, info
.border
,
231 info
.format
, info
.type
, info
.image
.get() != NULL
,
232 CanRender(feature_info
), CanRenderTo(), npot_
,
233 min_filter_
, mag_filter_
, wrap_s_
, wrap_t_
,
237 void Texture::SetMailboxManager(MailboxManager
* mailbox_manager
) {
238 DCHECK(!mailbox_manager_
|| mailbox_manager_
== mailbox_manager
);
239 mailbox_manager_
= mailbox_manager
;
242 bool Texture::MarkMipmapsGenerated(
243 const FeatureInfo
* feature_info
) {
244 if (!CanGenerateMipmaps(feature_info
)) {
247 for (size_t ii
= 0; ii
< level_infos_
.size(); ++ii
) {
248 const Texture::LevelInfo
& info1
= level_infos_
[ii
][0];
249 GLsizei width
= info1
.width
;
250 GLsizei height
= info1
.height
;
251 GLsizei depth
= info1
.depth
;
252 GLenum target
= target_
== GL_TEXTURE_2D
? GL_TEXTURE_2D
:
253 GLES2Util::IndexToGLFaceTarget(ii
);
255 TextureManager::ComputeMipMapCount(target_
, width
, height
, depth
);
256 for (int level
= 1; level
< num_mips
; ++level
) {
257 width
= std::max(1, width
>> 1);
258 height
= std::max(1, height
>> 1);
259 depth
= std::max(1, depth
>> 1);
260 SetLevelInfo(feature_info
,
263 info1
.internal_format
,
277 void Texture::SetTarget(
278 const FeatureInfo
* feature_info
, GLenum target
, GLint max_levels
) {
279 DCHECK_EQ(0u, target_
); // you can only set this once.
281 size_t num_faces
= (target
== GL_TEXTURE_CUBE_MAP
) ? 6 : 1;
282 level_infos_
.resize(num_faces
);
283 for (size_t ii
= 0; ii
< num_faces
; ++ii
) {
284 level_infos_
[ii
].resize(max_levels
);
287 if (target
== GL_TEXTURE_EXTERNAL_OES
|| target
== GL_TEXTURE_RECTANGLE_ARB
) {
288 min_filter_
= GL_LINEAR
;
289 wrap_s_
= wrap_t_
= GL_CLAMP_TO_EDGE
;
292 if (target
== GL_TEXTURE_EXTERNAL_OES
) {
295 Update(feature_info
);
296 UpdateCanRenderCondition();
299 bool Texture::CanGenerateMipmaps(
300 const FeatureInfo
* feature_info
) const {
301 if ((npot() && !feature_info
->feature_flags().npot_ok
) ||
302 level_infos_
.empty() ||
303 target_
== GL_TEXTURE_EXTERNAL_OES
||
304 target_
== GL_TEXTURE_RECTANGLE_ARB
) {
308 // Can't generate mips for depth or stencil textures.
309 const Texture::LevelInfo
& first
= level_infos_
[0][0];
310 uint32 channels
= GLES2Util::GetChannelsForFormat(first
.format
);
311 if (channels
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) {
315 // TODO(gman): Check internal_format, format and type.
316 for (size_t ii
= 0; ii
< level_infos_
.size(); ++ii
) {
317 const LevelInfo
& info
= level_infos_
[ii
][0];
318 if ((info
.target
== 0) || (info
.width
!= first
.width
) ||
319 (info
.height
!= first
.height
) || (info
.depth
!= 1) ||
320 (info
.format
!= first
.format
) ||
321 (info
.internal_format
!= first
.internal_format
) ||
322 (info
.type
!= first
.type
) ||
323 feature_info
->validators()->compressed_texture_format
.IsValid(
324 info
.internal_format
) ||
332 void Texture::SetLevelCleared(GLenum target
, GLint level
, bool cleared
) {
334 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
335 DCHECK_LT(static_cast<size_t>(face_index
),
336 level_infos_
.size());
337 DCHECK_LT(static_cast<size_t>(level
),
338 level_infos_
[face_index
].size());
339 Texture::LevelInfo
& info
=
340 level_infos_
[face_index
][level
];
341 UpdateMipCleared(&info
, cleared
);
345 void Texture::UpdateCleared() {
346 if (level_infos_
.empty()) {
350 const Texture::LevelInfo
& first_face
= level_infos_
[0][0];
351 int levels_needed
= TextureManager::ComputeMipMapCount(
352 target_
, first_face
.width
, first_face
.height
, first_face
.depth
);
354 for (size_t ii
= 0; ii
< level_infos_
.size(); ++ii
) {
355 for (GLint jj
= 0; jj
< levels_needed
; ++jj
) {
356 const Texture::LevelInfo
& info
= level_infos_
[ii
][jj
];
357 if (info
.width
> 0 && info
.height
> 0 && info
.depth
> 0 &&
365 // If texture is uncleared and is attached to a framebuffer,
366 // that framebuffer must be marked possibly incomplete.
367 if (!cleared
&& IsAttachedToFramebuffer()) {
368 IncAllFramebufferStateChangeCount();
371 UpdateSafeToRenderFrom(cleared
);
374 void Texture::UpdateSafeToRenderFrom(bool cleared
) {
375 if (cleared_
== cleared
)
378 int delta
= cleared
? -1 : +1;
379 for (RefSet::iterator it
= refs_
.begin(); it
!= refs_
.end(); ++it
)
380 (*it
)->manager()->UpdateSafeToRenderFrom(delta
);
383 void Texture::UpdateMipCleared(LevelInfo
* info
, bool cleared
) {
384 if (info
->cleared
== cleared
)
386 info
->cleared
= cleared
;
387 int delta
= cleared
? -1 : +1;
388 num_uncleared_mips_
+= delta
;
389 for (RefSet::iterator it
= refs_
.begin(); it
!= refs_
.end(); ++it
)
390 (*it
)->manager()->UpdateUnclearedMips(delta
);
393 void Texture::UpdateCanRenderCondition() {
394 CanRenderCondition can_render_condition
= GetCanRenderCondition();
395 if (can_render_condition_
== can_render_condition
)
397 for (RefSet::iterator it
= refs_
.begin(); it
!= refs_
.end(); ++it
)
398 (*it
)->manager()->UpdateCanRenderCondition(can_render_condition_
,
399 can_render_condition
);
400 can_render_condition_
= can_render_condition
;
403 void Texture::UpdateHasImages() {
404 if (level_infos_
.empty())
407 bool has_images
= false;
408 for (size_t ii
= 0; ii
< level_infos_
.size(); ++ii
) {
409 for (size_t jj
= 0; jj
< level_infos_
[ii
].size(); ++jj
) {
410 const Texture::LevelInfo
& info
= level_infos_
[ii
][jj
];
411 if (info
.image
.get() != NULL
) {
418 if (has_images_
== has_images
)
420 has_images_
= has_images
;
421 int delta
= has_images
? +1 : -1;
422 for (RefSet::iterator it
= refs_
.begin(); it
!= refs_
.end(); ++it
)
423 (*it
)->manager()->UpdateNumImages(delta
);
426 void Texture::IncAllFramebufferStateChangeCount() {
427 for (RefSet::iterator it
= refs_
.begin(); it
!= refs_
.end(); ++it
)
428 (*it
)->manager()->IncFramebufferStateChangeCount();
431 void Texture::SetLevelInfo(
432 const FeatureInfo
* feature_info
,
435 GLenum internal_format
,
444 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
445 DCHECK_LT(static_cast<size_t>(face_index
),
446 level_infos_
.size());
447 DCHECK_LT(static_cast<size_t>(level
),
448 level_infos_
[face_index
].size());
450 DCHECK_GE(height
, 0);
452 Texture::LevelInfo
& info
=
453 level_infos_
[face_index
][level
];
454 info
.target
= target
;
456 info
.internal_format
= internal_format
;
458 info
.height
= height
;
460 info
.border
= border
;
461 info
.format
= format
;
465 estimated_size_
-= info
.estimated_size
;
466 GLES2Util::ComputeImageDataSizes(
467 width
, height
, format
, type
, 4, &info
.estimated_size
, NULL
, NULL
);
468 estimated_size_
+= info
.estimated_size
;
470 UpdateMipCleared(&info
, cleared
);
471 max_level_set_
= std::max(max_level_set_
, level
);
472 Update(feature_info
);
474 UpdateCanRenderCondition();
476 if (IsAttachedToFramebuffer()) {
477 // TODO(gman): If textures tracked which framebuffers they were attached to
478 // we could just mark those framebuffers as not complete.
479 IncAllFramebufferStateChangeCount();
483 bool Texture::ValidForTexture(
491 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
492 if (level
>= 0 && face_index
< level_infos_
.size() &&
493 static_cast<size_t>(level
) < level_infos_
[face_index
].size()) {
494 const LevelInfo
& info
= level_infos_
[face_index
][level
];
497 return SafeAddInt32(xoffset
, width
, &right
) &&
498 SafeAddInt32(yoffset
, height
, &top
) &&
501 right
<= info
.width
&&
502 top
<= info
.height
&&
508 bool Texture::GetLevelSize(
509 GLint target
, GLint level
, GLsizei
* width
, GLsizei
* height
) const {
512 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
513 if (level
>= 0 && face_index
< level_infos_
.size() &&
514 static_cast<size_t>(level
) < level_infos_
[face_index
].size()) {
515 const LevelInfo
& info
= level_infos_
[face_index
][level
];
516 if (info
.target
!= 0) {
518 *height
= info
.height
;
525 bool Texture::GetLevelType(
526 GLint target
, GLint level
, GLenum
* type
, GLenum
* internal_format
) const {
528 DCHECK(internal_format
);
529 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
530 if (level
>= 0 && face_index
< level_infos_
.size() &&
531 static_cast<size_t>(level
) < level_infos_
[face_index
].size()) {
532 const LevelInfo
& info
= level_infos_
[face_index
][level
];
533 if (info
.target
!= 0) {
535 *internal_format
= info
.internal_format
;
542 GLenum
Texture::SetParameteri(
543 const FeatureInfo
* feature_info
, GLenum pname
, GLint param
) {
544 DCHECK(feature_info
);
546 if (target_
== GL_TEXTURE_EXTERNAL_OES
||
547 target_
== GL_TEXTURE_RECTANGLE_ARB
) {
548 if (pname
== GL_TEXTURE_MIN_FILTER
&&
549 (param
!= GL_NEAREST
&& param
!= GL_LINEAR
))
550 return GL_INVALID_ENUM
;
551 if ((pname
== GL_TEXTURE_WRAP_S
|| pname
== GL_TEXTURE_WRAP_T
) &&
552 param
!= GL_CLAMP_TO_EDGE
)
553 return GL_INVALID_ENUM
;
557 case GL_TEXTURE_MIN_FILTER
:
558 if (!feature_info
->validators()->texture_min_filter_mode
.IsValid(param
)) {
559 return GL_INVALID_ENUM
;
563 case GL_TEXTURE_MAG_FILTER
:
564 if (!feature_info
->validators()->texture_mag_filter_mode
.IsValid(param
)) {
565 return GL_INVALID_ENUM
;
569 case GL_TEXTURE_POOL_CHROMIUM
:
570 if (!feature_info
->validators()->texture_pool
.IsValid(param
)) {
571 return GL_INVALID_ENUM
;
573 GetMemTracker()->TrackMemFree(estimated_size());
575 GetMemTracker()->TrackMemAlloc(estimated_size());
577 case GL_TEXTURE_WRAP_S
:
578 if (!feature_info
->validators()->texture_wrap_mode
.IsValid(param
)) {
579 return GL_INVALID_ENUM
;
583 case GL_TEXTURE_WRAP_T
:
584 if (!feature_info
->validators()->texture_wrap_mode
.IsValid(param
)) {
585 return GL_INVALID_ENUM
;
589 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
591 return GL_INVALID_VALUE
;
594 case GL_TEXTURE_USAGE_ANGLE
:
595 if (!feature_info
->validators()->texture_usage
.IsValid(param
)) {
596 return GL_INVALID_ENUM
;
602 return GL_INVALID_ENUM
;
604 Update(feature_info
);
606 UpdateCanRenderCondition();
610 GLenum
Texture::SetParameterf(
611 const FeatureInfo
* feature_info
, GLenum pname
, GLfloat param
) {
613 case GL_TEXTURE_MIN_FILTER
:
614 case GL_TEXTURE_MAG_FILTER
:
615 case GL_TEXTURE_POOL_CHROMIUM
:
616 case GL_TEXTURE_WRAP_S
:
617 case GL_TEXTURE_WRAP_T
:
618 case GL_TEXTURE_USAGE_ANGLE
:
620 GLint iparam
= static_cast<GLint
>(param
);
621 return SetParameteri(feature_info
, pname
, iparam
);
623 case GL_TEXTURE_MAX_ANISOTROPY_EXT
:
625 return GL_INVALID_VALUE
;
630 return GL_INVALID_ENUM
;
635 void Texture::Update(const FeatureInfo
* feature_info
) {
636 // Update npot status.
637 // Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others
638 npot_
= target_
== GL_TEXTURE_EXTERNAL_OES
;
640 if (level_infos_
.empty()) {
641 texture_complete_
= false;
642 cube_complete_
= false;
646 // checks that the first mip of any face is npot.
647 for (size_t ii
= 0; ii
< level_infos_
.size(); ++ii
) {
648 const Texture::LevelInfo
& info
= level_infos_
[ii
][0];
649 if (GLES2Util::IsNPOT(info
.width
) ||
650 GLES2Util::IsNPOT(info
.height
) ||
651 GLES2Util::IsNPOT(info
.depth
)) {
657 // Update texture_complete and cube_complete status.
658 const Texture::LevelInfo
& first_face
= level_infos_
[0][0];
659 int levels_needed
= TextureManager::ComputeMipMapCount(
660 target_
, first_face
.width
, first_face
.height
, first_face
.depth
);
662 max_level_set_
>= (levels_needed
- 1) && max_level_set_
>= 0;
663 cube_complete_
= (level_infos_
.size() == 6) &&
664 (first_face
.width
== first_face
.height
);
666 if (first_face
.width
== 0 || first_face
.height
== 0) {
667 texture_complete_
= false;
669 if (first_face
.type
== GL_FLOAT
&&
670 !feature_info
->feature_flags().enable_texture_float_linear
&&
671 (min_filter_
!= GL_NEAREST_MIPMAP_NEAREST
||
672 mag_filter_
!= GL_NEAREST
)) {
673 texture_complete_
= false;
674 } else if (first_face
.type
== GL_HALF_FLOAT_OES
&&
675 !feature_info
->feature_flags().enable_texture_half_float_linear
&&
676 (min_filter_
!= GL_NEAREST_MIPMAP_NEAREST
||
677 mag_filter_
!= GL_NEAREST
)) {
678 texture_complete_
= false;
681 ii
< level_infos_
.size() && (cube_complete_
|| texture_complete_
);
683 const Texture::LevelInfo
& level0
= level_infos_
[ii
][0];
684 if (level0
.target
== 0 ||
685 level0
.width
!= first_face
.width
||
686 level0
.height
!= first_face
.height
||
688 level0
.internal_format
!= first_face
.internal_format
||
689 level0
.format
!= first_face
.format
||
690 level0
.type
!= first_face
.type
) {
691 cube_complete_
= false;
693 // Get level0 dimensions
694 GLsizei width
= level0
.width
;
695 GLsizei height
= level0
.height
;
696 GLsizei depth
= level0
.depth
;
697 for (GLint jj
= 1; jj
< levels_needed
; ++jj
) {
698 // compute required size for mip.
699 width
= std::max(1, width
>> 1);
700 height
= std::max(1, height
>> 1);
701 depth
= std::max(1, depth
>> 1);
702 const Texture::LevelInfo
& info
= level_infos_
[ii
][jj
];
703 if (info
.target
== 0 ||
704 info
.width
!= width
||
705 info
.height
!= height
||
706 info
.depth
!= depth
||
707 info
.internal_format
!= level0
.internal_format
||
708 info
.format
!= level0
.format
||
709 info
.type
!= level0
.type
) {
710 texture_complete_
= false;
717 bool Texture::ClearRenderableLevels(GLES2Decoder
* decoder
) {
723 const Texture::LevelInfo
& first_face
= level_infos_
[0][0];
724 int levels_needed
= TextureManager::ComputeMipMapCount(
725 target_
, first_face
.width
, first_face
.height
, first_face
.depth
);
727 for (size_t ii
= 0; ii
< level_infos_
.size(); ++ii
) {
728 for (GLint jj
= 0; jj
< levels_needed
; ++jj
) {
729 Texture::LevelInfo
& info
= level_infos_
[ii
][jj
];
730 if (info
.target
!= 0) {
731 if (!ClearLevel(decoder
, info
.target
, jj
)) {
737 UpdateSafeToRenderFrom(true);
741 bool Texture::IsLevelCleared(GLenum target
, GLint level
) const {
742 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
743 if (face_index
>= level_infos_
.size() ||
744 level
>= static_cast<GLint
>(level_infos_
[face_index
].size())) {
748 const Texture::LevelInfo
& info
= level_infos_
[face_index
][level
];
753 void Texture::InitTextureMaxAnisotropyIfNeeded(GLenum target
) {
754 if (texture_max_anisotropy_initialized_
)
756 texture_max_anisotropy_initialized_
= true;
757 GLfloat params
[] = { 1.0f
};
758 glTexParameterfv(target
, GL_TEXTURE_MAX_ANISOTROPY_EXT
, params
);
761 bool Texture::ClearLevel(
762 GLES2Decoder
* decoder
, GLenum target
, GLint level
) {
764 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
765 if (face_index
>= level_infos_
.size() ||
766 level
>= static_cast<GLint
>(level_infos_
[face_index
].size())) {
770 Texture::LevelInfo
& info
= level_infos_
[face_index
][level
];
772 DCHECK(target
== info
.target
);
774 if (info
.target
== 0 ||
782 // NOTE: It seems kind of gross to call back into the decoder for this
783 // but only the decoder knows all the state (like unpack_alignment_) that's
784 // needed to be able to call GL correctly.
785 bool cleared
= decoder
->ClearLevel(
786 service_id_
, target_
, info
.target
, info
.level
, info
.internal_format
,
787 info
.format
, info
.type
, info
.width
, info
.height
, immutable_
);
788 UpdateMipCleared(&info
, cleared
);
792 void Texture::SetLevelImage(
793 const FeatureInfo
* feature_info
,
796 gfx::GLImage
* image
) {
798 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
799 DCHECK_LT(static_cast<size_t>(face_index
),
800 level_infos_
.size());
801 DCHECK_LT(static_cast<size_t>(level
),
802 level_infos_
[face_index
].size());
803 Texture::LevelInfo
& info
=
804 level_infos_
[face_index
][level
];
805 DCHECK_EQ(info
.target
, target
);
806 DCHECK_EQ(info
.level
, level
);
808 UpdateCanRenderCondition();
812 gfx::GLImage
* Texture::GetLevelImage(GLint target
, GLint level
) const {
813 if (target
!= GL_TEXTURE_2D
&& target
!= GL_TEXTURE_EXTERNAL_OES
&&
814 target
!= GL_TEXTURE_RECTANGLE_ARB
) {
818 size_t face_index
= GLES2Util::GLTargetToFaceIndex(target
);
819 if (level
>= 0 && face_index
< level_infos_
.size() &&
820 static_cast<size_t>(level
) < level_infos_
[face_index
].size()) {
821 const LevelInfo
& info
= level_infos_
[face_index
][level
];
822 if (info
.target
!= 0) {
823 return info
.image
.get();
829 void Texture::OnWillModifyPixels() {
830 gfx::GLImage
* image
= GetLevelImage(target(), 0);
832 image
->WillModifyTexImage();
835 void Texture::OnDidModifyPixels() {
836 gfx::GLImage
* image
= GetLevelImage(target(), 0);
838 image
->DidModifyTexImage();
841 TextureRef::TextureRef(TextureManager
* manager
,
846 client_id_(client_id
),
850 texture_
->AddTextureRef(this);
851 manager_
->StartTracking(this);
854 scoped_refptr
<TextureRef
> TextureRef::Create(TextureManager
* manager
,
857 return new TextureRef(manager
, client_id
, new Texture(service_id
));
860 TextureRef::~TextureRef() {
861 manager_
->StopTracking(this);
862 texture_
->RemoveTextureRef(this, manager_
->have_context_
);
866 TextureManager::TextureManager(MemoryTracker
* memory_tracker
,
867 FeatureInfo
* feature_info
,
868 GLint max_texture_size
,
869 GLint max_cube_map_texture_size
,
870 bool use_default_textures
)
871 : memory_tracker_managed_(
872 new MemoryTypeTracker(memory_tracker
, MemoryTracker::kManaged
)),
873 memory_tracker_unmanaged_(
874 new MemoryTypeTracker(memory_tracker
, MemoryTracker::kUnmanaged
)),
875 feature_info_(feature_info
),
876 framebuffer_manager_(NULL
),
877 max_texture_size_(max_texture_size
),
878 max_cube_map_texture_size_(max_cube_map_texture_size
),
879 max_levels_(ComputeMipMapCount(GL_TEXTURE_2D
,
883 max_cube_map_levels_(ComputeMipMapCount(GL_TEXTURE_CUBE_MAP
,
884 max_cube_map_texture_size
,
885 max_cube_map_texture_size
,
886 max_cube_map_texture_size
)),
887 use_default_textures_(use_default_textures
),
888 num_unrenderable_textures_(0),
889 num_unsafe_textures_(0),
890 num_uncleared_mips_(0),
893 have_context_(true) {
894 for (int ii
= 0; ii
< kNumDefaultTextures
; ++ii
) {
895 black_texture_ids_
[ii
] = 0;
899 bool TextureManager::Initialize() {
900 // TODO(gman): The default textures have to be real textures, not the 0
901 // texture because we simulate non shared resources on top of shared
902 // resources and all contexts that share resource share the same default
904 default_textures_
[kTexture2D
] = CreateDefaultAndBlackTextures(
905 GL_TEXTURE_2D
, &black_texture_ids_
[kTexture2D
]);
906 default_textures_
[kCubeMap
] = CreateDefaultAndBlackTextures(
907 GL_TEXTURE_CUBE_MAP
, &black_texture_ids_
[kCubeMap
]);
909 if (feature_info_
->feature_flags().oes_egl_image_external
) {
910 default_textures_
[kExternalOES
] = CreateDefaultAndBlackTextures(
911 GL_TEXTURE_EXTERNAL_OES
, &black_texture_ids_
[kExternalOES
]);
914 if (feature_info_
->feature_flags().arb_texture_rectangle
) {
915 default_textures_
[kRectangleARB
] = CreateDefaultAndBlackTextures(
916 GL_TEXTURE_RECTANGLE_ARB
, &black_texture_ids_
[kRectangleARB
]);
922 scoped_refptr
<TextureRef
>
923 TextureManager::CreateDefaultAndBlackTextures(
925 GLuint
* black_texture
) {
926 static uint8 black
[] = {0, 0, 0, 255};
928 // Sampling a texture not associated with any EGLImage sibling will return
929 // black values according to the spec.
930 bool needs_initialization
= (target
!= GL_TEXTURE_EXTERNAL_OES
);
931 bool needs_faces
= (target
== GL_TEXTURE_CUBE_MAP
);
933 // Make default textures and texture for replacing non-renderable textures.
935 const int num_ids
= use_default_textures_
? 2 : 1;
936 glGenTextures(num_ids
, ids
);
937 for (int ii
= 0; ii
< num_ids
; ++ii
) {
938 glBindTexture(target
, ids
[ii
]);
939 if (needs_initialization
) {
941 for (int jj
= 0; jj
< GLES2Util::kNumFaces
; ++jj
) {
942 glTexImage2D(GLES2Util::IndexToGLFaceTarget(jj
), 0, GL_RGBA
, 1, 1, 0,
943 GL_RGBA
, GL_UNSIGNED_BYTE
, black
);
946 glTexImage2D(target
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
,
947 GL_UNSIGNED_BYTE
, black
);
951 glBindTexture(target
, 0);
953 scoped_refptr
<TextureRef
> default_texture
;
954 if (use_default_textures_
) {
955 default_texture
= TextureRef::Create(this, 0, ids
[1]);
956 SetTarget(default_texture
.get(), target
);
958 for (int ii
= 0; ii
< GLES2Util::kNumFaces
; ++ii
) {
959 SetLevelInfo(default_texture
.get(),
960 GLES2Util::IndexToGLFaceTarget(ii
),
972 if (needs_initialization
) {
973 SetLevelInfo(default_texture
.get(),
985 SetLevelInfo(default_texture
.get(),
986 GL_TEXTURE_EXTERNAL_OES
,
1000 *black_texture
= ids
[0];
1001 return default_texture
;
1004 bool TextureManager::ValidForTarget(
1005 GLenum target
, GLint level
, GLsizei width
, GLsizei height
, GLsizei depth
) {
1006 GLsizei max_size
= MaxSizeForTarget(target
) >> level
;
1007 return level
>= 0 &&
1011 level
< MaxLevelsForTarget(target
) &&
1012 width
<= max_size
&&
1013 height
<= max_size
&&
1014 depth
<= max_size
&&
1015 (level
== 0 || feature_info_
->feature_flags().npot_ok
||
1016 (!GLES2Util::IsNPOT(width
) &&
1017 !GLES2Util::IsNPOT(height
) &&
1018 !GLES2Util::IsNPOT(depth
))) &&
1019 (target
!= GL_TEXTURE_CUBE_MAP
|| (width
== height
&& depth
== 1)) &&
1020 (target
!= GL_TEXTURE_2D
|| (depth
== 1));
1023 void TextureManager::SetTarget(TextureRef
* ref
, GLenum target
) {
1026 ->SetTarget(feature_info_
.get(), target
, MaxLevelsForTarget(target
));
1029 void TextureManager::SetLevelCleared(TextureRef
* ref
,
1034 ref
->texture()->SetLevelCleared(target
, level
, cleared
);
1037 bool TextureManager::ClearRenderableLevels(
1038 GLES2Decoder
* decoder
, TextureRef
* ref
) {
1040 return ref
->texture()->ClearRenderableLevels(decoder
);
1043 bool TextureManager::ClearTextureLevel(
1044 GLES2Decoder
* decoder
, TextureRef
* ref
,
1045 GLenum target
, GLint level
) {
1047 Texture
* texture
= ref
->texture();
1048 if (texture
->num_uncleared_mips() == 0) {
1051 bool result
= texture
->ClearLevel(decoder
, target
, level
);
1052 texture
->UpdateCleared();
1056 void TextureManager::SetLevelInfo(
1060 GLenum internal_format
,
1069 Texture
* texture
= ref
->texture();
1071 texture
->GetMemTracker()->TrackMemFree(texture
->estimated_size());
1072 texture
->SetLevelInfo(feature_info_
.get(),
1083 texture
->GetMemTracker()->TrackMemAlloc(texture
->estimated_size());
1086 Texture
* TextureManager::Produce(TextureRef
* ref
) {
1088 return ref
->texture();
1091 TextureRef
* TextureManager::Consume(
1095 scoped_refptr
<TextureRef
> ref(new TextureRef(this, client_id
, texture
));
1096 bool result
= textures_
.insert(std::make_pair(client_id
, ref
)).second
;
1101 void TextureManager::SetParameteri(
1102 const char* function_name
, ErrorState
* error_state
,
1103 TextureRef
* ref
, GLenum pname
, GLint param
) {
1104 DCHECK(error_state
);
1106 Texture
* texture
= ref
->texture();
1107 GLenum result
= texture
->SetParameteri(feature_info_
.get(), pname
, param
);
1108 if (result
!= GL_NO_ERROR
) {
1109 if (result
== GL_INVALID_ENUM
) {
1110 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1111 error_state
, function_name
, param
, "param");
1113 ERRORSTATE_SET_GL_ERROR_INVALID_PARAMI(
1114 error_state
, result
, function_name
, pname
, param
);
1117 // Texture tracking pools exist only for the command decoder, so
1118 // do not pass them on to the native GL implementation.
1119 if (pname
!= GL_TEXTURE_POOL_CHROMIUM
) {
1120 glTexParameteri(texture
->target(), pname
, param
);
1125 void TextureManager::SetParameterf(
1126 const char* function_name
, ErrorState
* error_state
,
1127 TextureRef
* ref
, GLenum pname
, GLfloat param
) {
1128 DCHECK(error_state
);
1130 Texture
* texture
= ref
->texture();
1131 GLenum result
= texture
->SetParameterf(feature_info_
.get(), pname
, param
);
1132 if (result
!= GL_NO_ERROR
) {
1133 if (result
== GL_INVALID_ENUM
) {
1134 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1135 error_state
, function_name
, param
, "param");
1137 ERRORSTATE_SET_GL_ERROR_INVALID_PARAMF(
1138 error_state
, result
, function_name
, pname
, param
);
1141 // Texture tracking pools exist only for the command decoder, so
1142 // do not pass them on to the native GL implementation.
1143 if (pname
!= GL_TEXTURE_POOL_CHROMIUM
) {
1144 glTexParameterf(texture
->target(), pname
, param
);
1149 bool TextureManager::MarkMipmapsGenerated(TextureRef
* ref
) {
1151 Texture
* texture
= ref
->texture();
1152 texture
->GetMemTracker()->TrackMemFree(texture
->estimated_size());
1153 bool result
= texture
->MarkMipmapsGenerated(feature_info_
.get());
1154 texture
->GetMemTracker()->TrackMemAlloc(texture
->estimated_size());
1158 TextureRef
* TextureManager::CreateTexture(
1159 GLuint client_id
, GLuint service_id
) {
1160 DCHECK_NE(0u, service_id
);
1161 scoped_refptr
<TextureRef
> ref(TextureRef::Create(
1162 this, client_id
, service_id
));
1163 std::pair
<TextureMap::iterator
, bool> result
=
1164 textures_
.insert(std::make_pair(client_id
, ref
));
1165 DCHECK(result
.second
);
1169 TextureRef
* TextureManager::GetTexture(
1170 GLuint client_id
) const {
1171 TextureMap::const_iterator it
= textures_
.find(client_id
);
1172 return it
!= textures_
.end() ? it
->second
.get() : NULL
;
1175 void TextureManager::RemoveTexture(GLuint client_id
) {
1176 TextureMap::iterator it
= textures_
.find(client_id
);
1177 if (it
!= textures_
.end()) {
1178 it
->second
->reset_client_id();
1179 textures_
.erase(it
);
1183 void TextureManager::StartTracking(TextureRef
* ref
) {
1184 Texture
* texture
= ref
->texture();
1186 num_uncleared_mips_
+= texture
->num_uncleared_mips();
1187 if (!texture
->SafeToRenderFrom())
1188 ++num_unsafe_textures_
;
1189 if (!texture
->CanRender(feature_info_
.get()))
1190 ++num_unrenderable_textures_
;
1191 if (texture
->HasImages())
1195 void TextureManager::StopTracking(TextureRef
* ref
) {
1196 if (ref
->num_observers()) {
1197 for (unsigned int i
= 0; i
< destruction_observers_
.size(); i
++) {
1198 destruction_observers_
[i
]->OnTextureRefDestroying(ref
);
1200 DCHECK_EQ(ref
->num_observers(), 0);
1203 Texture
* texture
= ref
->texture();
1206 if (texture
->HasImages()) {
1207 DCHECK_NE(0, num_images_
);
1210 if (!texture
->CanRender(feature_info_
.get())) {
1211 DCHECK_NE(0, num_unrenderable_textures_
);
1212 --num_unrenderable_textures_
;
1214 if (!texture
->SafeToRenderFrom()) {
1215 DCHECK_NE(0, num_unsafe_textures_
);
1216 --num_unsafe_textures_
;
1218 num_uncleared_mips_
-= texture
->num_uncleared_mips();
1219 DCHECK_GE(num_uncleared_mips_
, 0);
1222 MemoryTypeTracker
* TextureManager::GetMemTracker(GLenum tracking_pool
) {
1223 switch (tracking_pool
) {
1224 case GL_TEXTURE_POOL_MANAGED_CHROMIUM
:
1225 return memory_tracker_managed_
.get();
1227 case GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
:
1228 return memory_tracker_unmanaged_
.get();
1237 Texture
* TextureManager::GetTextureForServiceId(GLuint service_id
) const {
1238 // This doesn't need to be fast. It's only used during slow queries.
1239 for (TextureMap::const_iterator it
= textures_
.begin();
1240 it
!= textures_
.end(); ++it
) {
1241 Texture
* texture
= it
->second
->texture();
1242 if (texture
->service_id() == service_id
)
1248 GLsizei
TextureManager::ComputeMipMapCount(GLenum target
,
1253 case GL_TEXTURE_EXTERNAL_OES
:
1257 base::bits::Log2Floor(std::max(std::max(width
, height
), depth
));
1261 void TextureManager::SetLevelImage(
1265 gfx::GLImage
* image
) {
1267 ref
->texture()->SetLevelImage(feature_info_
.get(), target
, level
, image
);
1270 void TextureManager::AddToSignature(
1274 std::string
* signature
) const {
1275 ref
->texture()->AddToSignature(feature_info_
.get(), target
, level
, signature
);
1278 void TextureManager::UpdateSafeToRenderFrom(int delta
) {
1279 num_unsafe_textures_
+= delta
;
1280 DCHECK_GE(num_unsafe_textures_
, 0);
1283 void TextureManager::UpdateUnclearedMips(int delta
) {
1284 num_uncleared_mips_
+= delta
;
1285 DCHECK_GE(num_uncleared_mips_
, 0);
1288 void TextureManager::UpdateCanRenderCondition(
1289 Texture::CanRenderCondition old_condition
,
1290 Texture::CanRenderCondition new_condition
) {
1291 if (old_condition
== Texture::CAN_RENDER_NEVER
||
1292 (old_condition
== Texture::CAN_RENDER_ONLY_IF_NPOT
&&
1293 !feature_info_
->feature_flags().npot_ok
)) {
1294 DCHECK_GT(num_unrenderable_textures_
, 0);
1295 --num_unrenderable_textures_
;
1297 if (new_condition
== Texture::CAN_RENDER_NEVER
||
1298 (new_condition
== Texture::CAN_RENDER_ONLY_IF_NPOT
&&
1299 !feature_info_
->feature_flags().npot_ok
))
1300 ++num_unrenderable_textures_
;
1303 void TextureManager::UpdateNumImages(int delta
) {
1304 num_images_
+= delta
;
1305 DCHECK_GE(num_images_
, 0);
1308 void TextureManager::IncFramebufferStateChangeCount() {
1309 if (framebuffer_manager_
)
1310 framebuffer_manager_
->IncFramebufferStateChangeCount();
1313 bool TextureManager::ValidateFormatAndTypeCombination(
1314 ErrorState
* error_state
, const char* function_name
, GLenum format
,
1316 if (!feature_info_
->GetTextureFormatValidator(format
).IsValid(type
)) {
1317 ERRORSTATE_SET_GL_ERROR(
1318 error_state
, GL_INVALID_OPERATION
, function_name
,
1319 (std::string("invalid type ") +
1320 GLES2Util::GetStringEnum(type
) + " for format " +
1321 GLES2Util::GetStringEnum(format
)).c_str());
1327 bool TextureManager::ValidateTextureParameters(
1328 ErrorState
* error_state
, const char* function_name
,
1329 GLenum format
, GLenum type
, GLenum internal_format
, GLint level
) {
1330 const Validators
* validators
= feature_info_
->validators();
1331 if (!validators
->texture_format
.IsValid(format
)) {
1332 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1333 error_state
, function_name
, format
, "format");
1336 if (!validators
->pixel_type
.IsValid(type
)) {
1337 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1338 error_state
, function_name
, type
, "type");
1341 if (format
!= internal_format
&&
1342 !((internal_format
== GL_RGBA32F
&& format
== GL_RGBA
) ||
1343 (internal_format
== GL_RGB32F
&& format
== GL_RGB
))) {
1344 ERRORSTATE_SET_GL_ERROR(
1345 error_state
, GL_INVALID_OPERATION
, function_name
,
1346 "format != internalformat");
1349 uint32 channels
= GLES2Util::GetChannelsForFormat(format
);
1350 if ((channels
& (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0 && level
) {
1351 ERRORSTATE_SET_GL_ERROR(
1352 error_state
, GL_INVALID_OPERATION
, function_name
,
1353 (std::string("invalid format ") + GLES2Util::GetStringEnum(format
) +
1354 " for level != 0").c_str());
1357 return ValidateFormatAndTypeCombination(error_state
, function_name
,
1361 // Gets the texture id for a given target.
1362 TextureRef
* TextureManager::GetTextureInfoForTarget(
1363 ContextState
* state
, GLenum target
) {
1364 TextureUnit
& unit
= state
->texture_units
[state
->active_texture_unit
];
1365 TextureRef
* texture
= NULL
;
1368 texture
= unit
.bound_texture_2d
.get();
1370 case GL_TEXTURE_CUBE_MAP
:
1371 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
1372 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
1373 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
1374 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
1375 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
1376 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
1377 texture
= unit
.bound_texture_cube_map
.get();
1379 case GL_TEXTURE_EXTERNAL_OES
:
1380 texture
= unit
.bound_texture_external_oes
.get();
1382 case GL_TEXTURE_RECTANGLE_ARB
:
1383 texture
= unit
.bound_texture_rectangle_arb
.get();
1392 TextureRef
* TextureManager::GetTextureInfoForTargetUnlessDefault(
1393 ContextState
* state
, GLenum target
) {
1394 TextureRef
* texture
= GetTextureInfoForTarget(state
, target
);
1397 if (texture
== GetDefaultTextureInfo(target
))
1402 bool TextureManager::ValidateTexImage2D(
1403 ContextState
* state
,
1404 const char* function_name
,
1405 const DoTextImage2DArguments
& args
,
1406 TextureRef
** texture_ref
) {
1407 ErrorState
* error_state
= state
->GetErrorState();
1408 const Validators
* validators
= feature_info_
->validators();
1409 if (!validators
->texture_target
.IsValid(args
.target
)) {
1410 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1411 error_state
, function_name
, args
.target
, "target");
1414 if (!validators
->texture_internal_format
.IsValid(args
.internal_format
)) {
1415 ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
1416 error_state
, function_name
, args
.internal_format
,
1420 if (!ValidateTextureParameters(
1421 error_state
, function_name
, args
.format
, args
.type
,
1422 args
.internal_format
, args
.level
)) {
1425 if (!ValidForTarget(args
.target
, args
.level
, args
.width
, args
.height
, 1) ||
1427 ERRORSTATE_SET_GL_ERROR(
1428 error_state
, GL_INVALID_VALUE
, function_name
,
1429 "dimensions out of range");
1432 if ((GLES2Util::GetChannelsForFormat(args
.format
) &
1433 (GLES2Util::kDepth
| GLES2Util::kStencil
)) != 0 && args
.pixels
) {
1434 ERRORSTATE_SET_GL_ERROR(
1435 error_state
, GL_INVALID_OPERATION
,
1436 function_name
, "can not supply data for depth or stencil textures");
1440 TextureRef
* local_texture_ref
= GetTextureInfoForTarget(state
, args
.target
);
1441 if (!local_texture_ref
) {
1442 ERRORSTATE_SET_GL_ERROR(
1443 error_state
, GL_INVALID_OPERATION
, function_name
,
1444 "unknown texture for target");
1447 if (local_texture_ref
->texture()->IsImmutable()) {
1448 ERRORSTATE_SET_GL_ERROR(
1449 error_state
, GL_INVALID_OPERATION
, function_name
,
1450 "texture is immutable");
1454 if (!memory_tracker_managed_
->EnsureGPUMemoryAvailable(args
.pixels_size
)) {
1455 ERRORSTATE_SET_GL_ERROR(error_state
, GL_OUT_OF_MEMORY
, function_name
,
1460 // Write the TextureReference since this is valid.
1461 *texture_ref
= local_texture_ref
;
1465 void TextureManager::ValidateAndDoTexImage2D(
1466 DecoderTextureState
* texture_state
,
1467 ContextState
* state
,
1468 DecoderFramebufferState
* framebuffer_state
,
1469 const DoTextImage2DArguments
& args
) {
1470 TextureRef
* texture_ref
;
1471 if (!ValidateTexImage2D(state
, "glTexImage2D", args
, &texture_ref
)) {
1475 DoTexImage2D(texture_state
, state
->GetErrorState(), framebuffer_state
,
1479 void TextureManager::DoTexImage2D(
1480 DecoderTextureState
* texture_state
,
1481 ErrorState
* error_state
,
1482 DecoderFramebufferState
* framebuffer_state
,
1483 TextureRef
* texture_ref
,
1484 const DoTextImage2DArguments
& args
) {
1485 Texture
* texture
= texture_ref
->texture();
1486 GLsizei tex_width
= 0;
1487 GLsizei tex_height
= 0;
1488 GLenum tex_type
= 0;
1489 GLenum tex_format
= 0;
1490 bool level_is_same
=
1491 texture
->GetLevelSize(args
.target
, args
.level
, &tex_width
, &tex_height
) &&
1492 texture
->GetLevelType(args
.target
, args
.level
, &tex_type
, &tex_format
) &&
1493 args
.width
== tex_width
&& args
.height
== tex_height
&&
1494 args
.type
== tex_type
&& args
.format
== tex_format
;
1496 if (level_is_same
&& !args
.pixels
) {
1497 // Just set the level texture but mark the texture as uncleared.
1500 args
.target
, args
.level
, args
.internal_format
, args
.width
, args
.height
,
1501 1, args
.border
, args
.format
, args
.type
, false);
1502 texture_state
->tex_image_2d_failed
= false;
1506 if (texture
->IsAttachedToFramebuffer()) {
1507 framebuffer_state
->clear_state_dirty
= true;
1510 if (texture_state
->texsubimage2d_faster_than_teximage2d
&&
1511 level_is_same
&& args
.pixels
) {
1513 ScopedTextureUploadTimer
timer(texture_state
);
1514 glTexSubImage2D(args
.target
, args
.level
, 0, 0, args
.width
, args
.height
,
1515 args
.format
, args
.type
, args
.pixels
);
1517 SetLevelCleared(texture_ref
, args
.target
, args
.level
, true);
1518 texture_state
->tex_image_2d_failed
= false;
1522 ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state
, "glTexImage2D");
1524 ScopedTextureUploadTimer
timer(texture_state
);
1526 args
.target
, args
.level
, args
.internal_format
, args
.width
, args
.height
,
1527 args
.border
, args
.format
, args
.type
, args
.pixels
);
1529 GLenum error
= ERRORSTATE_PEEK_GL_ERROR(error_state
, "glTexImage2D");
1530 if (error
== GL_NO_ERROR
) {
1533 args
.target
, args
.level
, args
.internal_format
, args
.width
, args
.height
,
1534 1, args
.border
, args
.format
, args
.type
, args
.pixels
!= NULL
);
1535 texture_state
->tex_image_2d_failed
= false;
1539 ScopedTextureUploadTimer::ScopedTextureUploadTimer(
1540 DecoderTextureState
* texture_state
)
1541 : texture_state_(texture_state
),
1542 begin_time_(base::TimeTicks::HighResNow()) {
1545 ScopedTextureUploadTimer::~ScopedTextureUploadTimer() {
1546 texture_state_
->texture_upload_count
++;
1547 texture_state_
->total_texture_upload_time
+=
1548 base::TimeTicks::HighResNow() - begin_time_
;
1551 } // namespace gles2