1 // Copyright 2013 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 "cc/test/test_web_graphics_context_3d.h"
10 #include "base/bind.h"
11 #include "base/lazy_instance.h"
12 #include "base/logging.h"
13 #include "base/message_loop/message_loop.h"
14 #include "cc/test/test_context_support.h"
15 #include "gpu/GLES2/gl2extchromium.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "third_party/khronos/GLES2/gl2ext.h"
21 static unsigned s_context_id
= 1;
23 const GLuint
TestWebGraphicsContext3D::kExternalTextureId
= 1337;
25 static base::LazyInstance
<base::Lock
>::Leaky
26 g_shared_namespace_lock
= LAZY_INSTANCE_INITIALIZER
;
28 TestWebGraphicsContext3D::Namespace
*
29 TestWebGraphicsContext3D::shared_namespace_
= NULL
;
31 TestWebGraphicsContext3D::Namespace::Namespace()
35 next_renderbuffer_id(1) {
38 TestWebGraphicsContext3D::Namespace::~Namespace() {
39 g_shared_namespace_lock
.Get().AssertAcquired();
40 if (shared_namespace_
== this)
41 shared_namespace_
= NULL
;
45 scoped_ptr
<TestWebGraphicsContext3D
> TestWebGraphicsContext3D::Create() {
46 return make_scoped_ptr(new TestWebGraphicsContext3D());
49 TestWebGraphicsContext3D::TestWebGraphicsContext3D()
50 : context_id_(s_context_id
++),
51 times_bind_texture_succeeds_(-1),
52 times_end_query_succeeds_(-1),
54 times_map_buffer_chromium_succeeds_(-1),
55 current_used_transfer_buffer_usage_bytes_(0),
56 max_used_transfer_buffer_usage_bytes_(0),
57 next_program_id_(1000),
58 next_shader_id_(2000),
59 next_framebuffer_id_(1),
60 current_framebuffer_(0),
61 max_texture_size_(2048),
62 reshape_called_(false),
67 last_update_type_(NoUpdate
),
68 next_insert_sync_point_(1),
69 last_waited_sync_point_(0),
72 weak_ptr_factory_(this) {
76 TestWebGraphicsContext3D::~TestWebGraphicsContext3D() {
77 base::AutoLock
lock(g_shared_namespace_lock
.Get());
81 void TestWebGraphicsContext3D::CreateNamespace() {
82 base::AutoLock
lock(g_shared_namespace_lock
.Get());
83 if (shared_namespace_
) {
84 namespace_
= shared_namespace_
;
86 namespace_
= new Namespace
;
87 shared_namespace_
= namespace_
.get();
91 void TestWebGraphicsContext3D::reshapeWithScaleFactor(
92 int width
, int height
, float scale_factor
) {
93 reshape_called_
= true;
96 scale_factor_
= scale_factor
;
99 bool TestWebGraphicsContext3D::isContextLost() {
100 return context_lost_
;
103 GLenum
TestWebGraphicsContext3D::checkFramebufferStatus(
106 return GL_FRAMEBUFFER_UNDEFINED_OES
;
107 return GL_FRAMEBUFFER_COMPLETE
;
110 GLint
TestWebGraphicsContext3D::getUniformLocation(
112 const GLchar
* name
) {
116 GLsizeiptr
TestWebGraphicsContext3D::getVertexAttribOffset(
122 GLboolean
TestWebGraphicsContext3D::isBuffer(
127 GLboolean
TestWebGraphicsContext3D::isEnabled(
132 GLboolean
TestWebGraphicsContext3D::isFramebuffer(
133 GLuint framebuffer
) {
137 GLboolean
TestWebGraphicsContext3D::isProgram(
142 GLboolean
TestWebGraphicsContext3D::isRenderbuffer(
143 GLuint renderbuffer
) {
147 GLboolean
TestWebGraphicsContext3D::isShader(
152 GLboolean
TestWebGraphicsContext3D::isTexture(
157 void TestWebGraphicsContext3D::genBuffers(GLsizei count
, GLuint
* ids
) {
158 for (int i
= 0; i
< count
; ++i
)
159 ids
[i
] = NextBufferId();
162 void TestWebGraphicsContext3D::genFramebuffers(
163 GLsizei count
, GLuint
* ids
) {
164 for (int i
= 0; i
< count
; ++i
)
165 ids
[i
] = NextFramebufferId();
168 void TestWebGraphicsContext3D::genRenderbuffers(
169 GLsizei count
, GLuint
* ids
) {
170 for (int i
= 0; i
< count
; ++i
)
171 ids
[i
] = NextRenderbufferId();
174 void TestWebGraphicsContext3D::genTextures(GLsizei count
, GLuint
* ids
) {
175 for (int i
= 0; i
< count
; ++i
) {
176 ids
[i
] = NextTextureId();
177 DCHECK_NE(ids
[i
], kExternalTextureId
);
179 base::AutoLock
lock(namespace_
->lock
);
180 for (int i
= 0; i
< count
; ++i
)
181 namespace_
->textures
.Append(ids
[i
], new TestTexture());
184 void TestWebGraphicsContext3D::deleteBuffers(GLsizei count
, GLuint
* ids
) {
185 for (int i
= 0; i
< count
; ++i
)
186 RetireBufferId(ids
[i
]);
189 void TestWebGraphicsContext3D::deleteFramebuffers(
190 GLsizei count
, GLuint
* ids
) {
191 for (int i
= 0; i
< count
; ++i
) {
193 RetireFramebufferId(ids
[i
]);
194 if (ids
[i
] == current_framebuffer_
)
195 current_framebuffer_
= 0;
200 void TestWebGraphicsContext3D::deleteRenderbuffers(
201 GLsizei count
, GLuint
* ids
) {
202 for (int i
= 0; i
< count
; ++i
)
203 RetireRenderbufferId(ids
[i
]);
206 void TestWebGraphicsContext3D::deleteTextures(GLsizei count
, GLuint
* ids
) {
207 for (int i
= 0; i
< count
; ++i
)
208 RetireTextureId(ids
[i
]);
209 base::AutoLock
lock(namespace_
->lock
);
210 for (int i
= 0; i
< count
; ++i
) {
211 namespace_
->textures
.Remove(ids
[i
]);
212 texture_targets_
.UnbindTexture(ids
[i
]);
216 GLuint
TestWebGraphicsContext3D::createBuffer() {
222 GLuint
TestWebGraphicsContext3D::createFramebuffer() {
224 genFramebuffers(1, &id
);
228 GLuint
TestWebGraphicsContext3D::createRenderbuffer() {
230 genRenderbuffers(1, &id
);
234 GLuint
TestWebGraphicsContext3D::createTexture() {
240 void TestWebGraphicsContext3D::deleteBuffer(GLuint id
) {
241 deleteBuffers(1, &id
);
244 void TestWebGraphicsContext3D::deleteFramebuffer(GLuint id
) {
245 deleteFramebuffers(1, &id
);
248 void TestWebGraphicsContext3D::deleteRenderbuffer(GLuint id
) {
249 deleteRenderbuffers(1, &id
);
252 void TestWebGraphicsContext3D::deleteTexture(GLuint id
) {
253 deleteTextures(1, &id
);
256 unsigned TestWebGraphicsContext3D::createProgram() {
257 unsigned program
= next_program_id_
++ | context_id_
<< 16;
258 program_set_
.insert(program
);
262 GLuint
TestWebGraphicsContext3D::createShader(GLenum
) {
263 unsigned shader
= next_shader_id_
++ | context_id_
<< 16;
264 shader_set_
.insert(shader
);
268 GLuint
TestWebGraphicsContext3D::createExternalTexture() {
269 base::AutoLock
lock(namespace_
->lock
);
270 namespace_
->textures
.Append(kExternalTextureId
, new TestTexture());
271 return kExternalTextureId
;
274 void TestWebGraphicsContext3D::deleteProgram(GLuint id
) {
275 if (!program_set_
.count(id
))
276 ADD_FAILURE() << "deleteProgram called on unknown program " << id
;
277 program_set_
.erase(id
);
280 void TestWebGraphicsContext3D::deleteShader(GLuint id
) {
281 if (!shader_set_
.count(id
))
282 ADD_FAILURE() << "deleteShader called on unknown shader " << id
;
283 shader_set_
.erase(id
);
286 void TestWebGraphicsContext3D::attachShader(GLuint program
, GLuint shader
) {
287 if (!program_set_
.count(program
))
288 ADD_FAILURE() << "attachShader called with unknown program " << program
;
289 if (!shader_set_
.count(shader
))
290 ADD_FAILURE() << "attachShader called with unknown shader " << shader
;
293 void TestWebGraphicsContext3D::useProgram(GLuint program
) {
296 if (!program_set_
.count(program
))
297 ADD_FAILURE() << "useProgram called on unknown program " << program
;
300 void TestWebGraphicsContext3D::bindFramebuffer(
301 GLenum target
, GLuint framebuffer
) {
302 base::AutoLock
lock_for_framebuffer_access(namespace_
->lock
);
303 if (framebuffer
!= 0 &&
304 framebuffer_set_
.find(framebuffer
) == framebuffer_set_
.end()) {
305 ADD_FAILURE() << "bindFramebuffer called with unknown framebuffer";
306 } else if (framebuffer
!= 0 && (framebuffer
>> 16) != context_id_
) {
308 << "bindFramebuffer called with framebuffer from other context";
310 current_framebuffer_
= framebuffer
;
314 void TestWebGraphicsContext3D::bindRenderbuffer(
315 GLenum target
, GLuint renderbuffer
) {
318 base::AutoLock
lock_for_renderbuffer_access(namespace_
->lock
);
319 if (renderbuffer
!= 0 &&
320 namespace_
->renderbuffer_set
.find(renderbuffer
) ==
321 namespace_
->renderbuffer_set
.end()) {
322 ADD_FAILURE() << "bindRenderbuffer called with unknown renderbuffer";
323 } else if ((renderbuffer
>> 16) != context_id_
) {
325 << "bindRenderbuffer called with renderbuffer from other context";
329 void TestWebGraphicsContext3D::bindTexture(
330 GLenum target
, GLuint texture_id
) {
331 if (times_bind_texture_succeeds_
>= 0) {
332 if (!times_bind_texture_succeeds_
) {
333 loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
334 GL_INNOCENT_CONTEXT_RESET_ARB
);
336 --times_bind_texture_succeeds_
;
341 base::AutoLock
lock(namespace_
->lock
);
342 DCHECK(namespace_
->textures
.ContainsId(texture_id
));
343 texture_targets_
.BindTexture(target
, texture_id
);
344 used_textures_
.insert(texture_id
);
347 GLuint
TestWebGraphicsContext3D::BoundTextureId(
349 return texture_targets_
.BoundTexture(target
);
352 scoped_refptr
<TestTexture
> TestWebGraphicsContext3D::BoundTexture(
354 // The caller is expected to lock the namespace for texture access.
355 namespace_
->lock
.AssertAcquired();
356 return namespace_
->textures
.TextureForId(BoundTextureId(target
));
359 void TestWebGraphicsContext3D::CheckTextureIsBound(GLenum target
) {
360 DCHECK(BoundTextureId(target
));
363 GLuint
TestWebGraphicsContext3D::createQueryEXT() { return 1u; }
365 void TestWebGraphicsContext3D::endQueryEXT(GLenum target
) {
366 if (times_end_query_succeeds_
>= 0) {
367 if (!times_end_query_succeeds_
) {
368 loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
369 GL_INNOCENT_CONTEXT_RESET_ARB
);
371 --times_end_query_succeeds_
;
375 void TestWebGraphicsContext3D::getQueryObjectuivEXT(
379 // If the context is lost, behave as if result is available.
380 if (pname
== GL_QUERY_RESULT_AVAILABLE_EXT
)
384 void TestWebGraphicsContext3D::getIntegerv(
387 if (pname
== GL_MAX_TEXTURE_SIZE
)
388 *value
= max_texture_size_
;
389 else if (pname
== GL_ACTIVE_TEXTURE
)
390 *value
= GL_TEXTURE0
;
391 else if (pname
== GL_UNPACK_ALIGNMENT
)
392 *value
= unpack_alignment_
;
393 else if (pname
== GL_FRAMEBUFFER_BINDING
)
394 *value
= current_framebuffer_
;
397 void TestWebGraphicsContext3D::getProgramiv(GLuint program
,
400 if (pname
== GL_LINK_STATUS
)
404 void TestWebGraphicsContext3D::getShaderiv(GLuint shader
,
407 if (pname
== GL_COMPILE_STATUS
)
411 void TestWebGraphicsContext3D::getShaderPrecisionFormat(GLenum shadertype
,
412 GLenum precisiontype
,
415 // Return the minimum precision requirements of the GLES2
417 switch (precisiontype
) {
438 case GL_MEDIUM_FLOAT
:
454 void TestWebGraphicsContext3D::genMailboxCHROMIUM(GLbyte
* mailbox
) {
455 static char mailbox_name1
= '1';
456 static char mailbox_name2
= '1';
457 mailbox
[0] = mailbox_name1
;
458 mailbox
[1] = mailbox_name2
;
460 if (++mailbox_name1
== 0) {
466 GLuint
TestWebGraphicsContext3D::createAndConsumeTextureCHROMIUM(
468 const GLbyte
* mailbox
) {
469 return createTexture();
472 void TestWebGraphicsContext3D::loseContextCHROMIUM(GLenum current
,
476 context_lost_
= true;
477 if (!context_lost_callback_
.is_null())
478 context_lost_callback_
.Run();
480 for (size_t i
= 0; i
< shared_contexts_
.size(); ++i
)
481 shared_contexts_
[i
]->loseContextCHROMIUM(current
, other
);
482 shared_contexts_
.clear();
485 void TestWebGraphicsContext3D::finish() {
486 test_support_
->CallAllSyncPointCallbacks();
489 void TestWebGraphicsContext3D::flush() {
490 test_support_
->CallAllSyncPointCallbacks();
493 GLint
TestWebGraphicsContext3D::getAttribLocation(GLuint program
,
494 const GLchar
* name
) {
498 GLenum
TestWebGraphicsContext3D::getError() { return GL_NO_ERROR
; }
500 void TestWebGraphicsContext3D::bindBuffer(GLenum target
,
502 bound_buffer_
= buffer
;
505 unsigned context_id
= buffer
>> 16;
506 unsigned buffer_id
= buffer
& 0xffff;
507 base::AutoLock
lock(namespace_
->lock
);
509 DCHECK_LT(buffer_id
, namespace_
->next_buffer_id
);
510 DCHECK_EQ(context_id
, context_id_
);
512 base::ScopedPtrHashMap
<unsigned, Buffer
>& buffers
= namespace_
->buffers
;
513 if (buffers
.count(bound_buffer_
) == 0)
514 buffers
.set(bound_buffer_
, make_scoped_ptr(new Buffer
).Pass());
516 buffers
.get(bound_buffer_
)->target
= target
;
519 void TestWebGraphicsContext3D::bufferData(GLenum target
,
523 base::AutoLock
lock(namespace_
->lock
);
524 base::ScopedPtrHashMap
<unsigned, Buffer
>& buffers
= namespace_
->buffers
;
525 DCHECK_GT(buffers
.count(bound_buffer_
), 0u);
526 DCHECK_EQ(target
, buffers
.get(bound_buffer_
)->target
);
527 Buffer
* buffer
= buffers
.get(bound_buffer_
);
529 buffer
->pixels
= nullptr;
533 size_t old_size
= buffer
->size
;
535 buffer
->pixels
.reset(new uint8
[size
]);
538 memcpy(buffer
->pixels
.get(), data
, size
);
539 if (buffer
->target
== GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM
)
540 current_used_transfer_buffer_usage_bytes_
+= buffer
->size
- old_size
;
541 max_used_transfer_buffer_usage_bytes_
=
542 std::max(max_used_transfer_buffer_usage_bytes_
,
543 current_used_transfer_buffer_usage_bytes_
);
546 void TestWebGraphicsContext3D::pixelStorei(GLenum pname
, GLint param
) {
548 case GL_UNPACK_ALIGNMENT
:
549 // Param should be a power of two <= 8.
550 EXPECT_EQ(0, param
& (param
- 1));
557 unpack_alignment_
= param
;
568 void* TestWebGraphicsContext3D::mapBufferCHROMIUM(GLenum target
,
570 base::AutoLock
lock(namespace_
->lock
);
571 base::ScopedPtrHashMap
<unsigned, Buffer
>& buffers
= namespace_
->buffers
;
572 DCHECK_GT(buffers
.count(bound_buffer_
), 0u);
573 DCHECK_EQ(target
, buffers
.get(bound_buffer_
)->target
);
574 if (times_map_buffer_chromium_succeeds_
>= 0) {
575 if (!times_map_buffer_chromium_succeeds_
) {
578 --times_map_buffer_chromium_succeeds_
;
581 return buffers
.get(bound_buffer_
)->pixels
.get();
584 GLboolean
TestWebGraphicsContext3D::unmapBufferCHROMIUM(
586 base::AutoLock
lock(namespace_
->lock
);
587 base::ScopedPtrHashMap
<unsigned, Buffer
>& buffers
= namespace_
->buffers
;
588 DCHECK_GT(buffers
.count(bound_buffer_
), 0u);
589 DCHECK_EQ(target
, buffers
.get(bound_buffer_
)->target
);
590 buffers
.get(bound_buffer_
)->pixels
= nullptr;
594 GLuint
TestWebGraphicsContext3D::createImageCHROMIUM(ClientBuffer buffer
,
597 GLenum internalformat
) {
598 DCHECK_EQ(GL_RGBA
, static_cast<int>(internalformat
));
599 GLuint image_id
= NextImageId();
600 base::AutoLock
lock(namespace_
->lock
);
601 base::hash_set
<unsigned>& images
= namespace_
->images
;
602 images
.insert(image_id
);
606 void TestWebGraphicsContext3D::destroyImageCHROMIUM(
609 base::AutoLock
lock(namespace_
->lock
);
610 base::hash_set
<unsigned>& images
= namespace_
->images
;
611 if (!images
.count(id
))
612 ADD_FAILURE() << "destroyImageCHROMIUM called on unknown image " << id
;
616 GLuint
TestWebGraphicsContext3D::createGpuMemoryBufferImageCHROMIUM(
619 GLenum internalformat
,
621 DCHECK_EQ(GL_RGBA
, static_cast<int>(internalformat
));
622 GLuint image_id
= NextImageId();
623 base::AutoLock
lock(namespace_
->lock
);
624 base::hash_set
<unsigned>& images
= namespace_
->images
;
625 images
.insert(image_id
);
629 unsigned TestWebGraphicsContext3D::insertSyncPoint() {
630 return next_insert_sync_point_
++;
633 void TestWebGraphicsContext3D::waitSyncPoint(unsigned sync_point
) {
635 last_waited_sync_point_
= sync_point
;
638 size_t TestWebGraphicsContext3D::NumTextures() const {
639 base::AutoLock
lock(namespace_
->lock
);
640 return namespace_
->textures
.Size();
643 GLuint
TestWebGraphicsContext3D::TextureAt(int i
) const {
644 base::AutoLock
lock(namespace_
->lock
);
645 return namespace_
->textures
.IdAt(i
);
648 GLuint
TestWebGraphicsContext3D::NextTextureId() {
649 base::AutoLock
lock(namespace_
->lock
);
650 GLuint texture_id
= namespace_
->next_texture_id
++;
651 DCHECK(texture_id
< (1 << 16));
652 texture_id
|= context_id_
<< 16;
656 void TestWebGraphicsContext3D::RetireTextureId(GLuint id
) {
657 base::AutoLock
lock(namespace_
->lock
);
658 unsigned context_id
= id
>> 16;
659 unsigned texture_id
= id
& 0xffff;
661 DCHECK_LT(texture_id
, namespace_
->next_texture_id
);
662 DCHECK_EQ(context_id
, context_id_
);
665 GLuint
TestWebGraphicsContext3D::NextBufferId() {
666 base::AutoLock
lock(namespace_
->lock
);
667 GLuint buffer_id
= namespace_
->next_buffer_id
++;
668 DCHECK(buffer_id
< (1 << 16));
669 buffer_id
|= context_id_
<< 16;
673 void TestWebGraphicsContext3D::RetireBufferId(GLuint id
) {
674 base::AutoLock
lock(namespace_
->lock
);
675 unsigned context_id
= id
>> 16;
676 unsigned buffer_id
= id
& 0xffff;
678 DCHECK_LT(buffer_id
, namespace_
->next_buffer_id
);
679 DCHECK_EQ(context_id
, context_id_
);
682 GLuint
TestWebGraphicsContext3D::NextImageId() {
683 base::AutoLock
lock(namespace_
->lock
);
684 GLuint image_id
= namespace_
->next_image_id
++;
685 DCHECK(image_id
< (1 << 16));
686 image_id
|= context_id_
<< 16;
690 void TestWebGraphicsContext3D::RetireImageId(GLuint id
) {
691 base::AutoLock
lock(namespace_
->lock
);
692 unsigned context_id
= id
>> 16;
693 unsigned image_id
= id
& 0xffff;
695 DCHECK_LT(image_id
, namespace_
->next_image_id
);
696 DCHECK_EQ(context_id
, context_id_
);
699 GLuint
TestWebGraphicsContext3D::NextFramebufferId() {
700 base::AutoLock
lock_for_framebuffer_access(namespace_
->lock
);
701 GLuint id
= next_framebuffer_id_
++;
702 DCHECK(id
< (1 << 16));
703 id
|= context_id_
<< 16;
704 framebuffer_set_
.insert(id
);
708 void TestWebGraphicsContext3D::RetireFramebufferId(GLuint id
) {
709 base::AutoLock
lock_for_framebuffer_access(namespace_
->lock
);
710 DCHECK(framebuffer_set_
.find(id
) != framebuffer_set_
.end());
711 framebuffer_set_
.erase(id
);
714 GLuint
TestWebGraphicsContext3D::NextRenderbufferId() {
715 base::AutoLock
lock_for_renderbuffer_access(namespace_
->lock
);
716 GLuint id
= namespace_
->next_renderbuffer_id
++;
717 DCHECK(id
< (1 << 16));
718 id
|= context_id_
<< 16;
719 namespace_
->renderbuffer_set
.insert(id
);
723 void TestWebGraphicsContext3D::RetireRenderbufferId(GLuint id
) {
724 base::AutoLock
lock_for_renderbuffer_access(namespace_
->lock
);
725 DCHECK(namespace_
->renderbuffer_set
.find(id
) !=
726 namespace_
->renderbuffer_set
.end());
727 namespace_
->renderbuffer_set
.erase(id
);
730 void TestWebGraphicsContext3D::SetMaxTransferBufferUsageBytes(
731 size_t max_transfer_buffer_usage_bytes
) {
732 test_capabilities_
.max_transfer_buffer_usage_bytes
=
733 max_transfer_buffer_usage_bytes
;
736 TestWebGraphicsContext3D::TextureTargets::TextureTargets() {
737 // Initialize default bindings.
738 bound_textures_
[GL_TEXTURE_2D
] = 0;
739 bound_textures_
[GL_TEXTURE_EXTERNAL_OES
] = 0;
740 bound_textures_
[GL_TEXTURE_RECTANGLE_ARB
] = 0;
743 TestWebGraphicsContext3D::TextureTargets::~TextureTargets() {}
745 void TestWebGraphicsContext3D::TextureTargets::BindTexture(
748 // Make sure this is a supported target by seeing if it was bound to before.
749 DCHECK(bound_textures_
.find(target
) != bound_textures_
.end());
750 bound_textures_
[target
] = id
;
753 void TestWebGraphicsContext3D::texParameteri(GLenum target
,
756 CheckTextureIsBound(target
);
757 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
758 scoped_refptr
<TestTexture
> texture
= BoundTexture(target
);
759 DCHECK(texture
->IsValidParameter(pname
));
760 texture
->params
[pname
] = param
;
763 void TestWebGraphicsContext3D::getTexParameteriv(GLenum target
,
766 CheckTextureIsBound(target
);
767 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
768 scoped_refptr
<TestTexture
> texture
= BoundTexture(target
);
769 DCHECK(texture
->IsValidParameter(pname
));
770 TestTexture::TextureParametersMap::iterator it
= texture
->params
.find(pname
);
771 if (it
!= texture
->params
.end())
775 void TestWebGraphicsContext3D::TextureTargets::UnbindTexture(
777 // Bind zero to any targets that the id is bound to.
778 for (TargetTextureMap::iterator it
= bound_textures_
.begin();
779 it
!= bound_textures_
.end();
781 if (it
->second
== id
)
786 GLuint
TestWebGraphicsContext3D::TextureTargets::BoundTexture(
788 DCHECK(bound_textures_
.find(target
) != bound_textures_
.end());
789 return bound_textures_
[target
];
792 TestWebGraphicsContext3D::Buffer::Buffer() : target(0), size(0) {}
794 TestWebGraphicsContext3D::Buffer::~Buffer() {}
796 TestWebGraphicsContext3D::Image::Image() {}
798 TestWebGraphicsContext3D::Image::~Image() {}