Fix web contents modal dialog crash in SimpleWebViewDialog
[chromium-blink-merge.git] / cc / debug / test_web_graphics_context_3d.cc
blob11d1ed8ec5d5518550f32847ee2fbaaf8c89ba12
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/debug/test_web_graphics_context_3d.h"
7 #include <algorithm>
8 #include <string>
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 "gpu/GLES2/gl2extchromium.h"
15 #include "third_party/khronos/GLES2/gl2ext.h"
17 using WebKit::WGC3Dboolean;
18 using WebKit::WGC3Dchar;
19 using WebKit::WGC3Denum;
20 using WebKit::WGC3Dint;
21 using WebKit::WGC3Dsizei;
22 using WebKit::WGC3Dsizeiptr;
23 using WebKit::WGC3Duint;
24 using WebKit::WebGLId;
25 using WebKit::WebGraphicsContext3D;
27 namespace cc {
29 static const WebGLId kFramebufferId = 1;
30 static const WebGLId kProgramId = 2;
31 static const WebGLId kRenderbufferId = 3;
32 static const WebGLId kShaderId = 4;
34 static unsigned s_context_id = 1;
36 const WebGLId TestWebGraphicsContext3D::kExternalTextureId = 1337;
38 static base::LazyInstance<base::Lock>::Leaky
39 g_shared_namespace_lock = LAZY_INSTANCE_INITIALIZER;
41 TestWebGraphicsContext3D::Namespace*
42 TestWebGraphicsContext3D::shared_namespace_ = NULL;
44 TestWebGraphicsContext3D::Namespace::Namespace()
45 : next_buffer_id(1),
46 next_image_id(1),
47 next_texture_id(1) {
50 TestWebGraphicsContext3D::Namespace::~Namespace() {
51 g_shared_namespace_lock.Get().AssertAcquired();
52 if (shared_namespace_ == this)
53 shared_namespace_ = NULL;
56 // static
57 scoped_ptr<TestWebGraphicsContext3D> TestWebGraphicsContext3D::Create() {
58 return make_scoped_ptr(new TestWebGraphicsContext3D());
61 TestWebGraphicsContext3D::TestWebGraphicsContext3D()
62 : FakeWebGraphicsContext3D(),
63 context_id_(s_context_id++),
64 support_swapbuffers_complete_callback_(true),
65 have_extension_io_surface_(false),
66 have_extension_egl_image_(false),
67 times_make_current_succeeds_(-1),
68 times_bind_texture_succeeds_(-1),
69 times_end_query_succeeds_(-1),
70 times_gen_mailbox_succeeds_(-1),
71 context_lost_(false),
72 times_map_image_chromium_succeeds_(-1),
73 times_map_buffer_chromium_succeeds_(-1),
74 context_lost_callback_(NULL),
75 swap_buffers_callback_(NULL),
76 max_texture_size_(2048),
77 width_(0),
78 height_(0),
79 bound_buffer_(0),
80 weak_ptr_factory_(this) {
81 CreateNamespace();
84 TestWebGraphicsContext3D::TestWebGraphicsContext3D(
85 const WebGraphicsContext3D::Attributes& attributes)
86 : FakeWebGraphicsContext3D(),
87 context_id_(s_context_id++),
88 attributes_(attributes),
89 support_swapbuffers_complete_callback_(true),
90 have_extension_io_surface_(false),
91 have_extension_egl_image_(false),
92 times_make_current_succeeds_(-1),
93 times_bind_texture_succeeds_(-1),
94 times_end_query_succeeds_(-1),
95 times_gen_mailbox_succeeds_(-1),
96 context_lost_(false),
97 times_map_image_chromium_succeeds_(-1),
98 times_map_buffer_chromium_succeeds_(-1),
99 context_lost_callback_(NULL),
100 swap_buffers_callback_(NULL),
101 max_texture_size_(2048),
102 width_(0),
103 height_(0),
104 bound_buffer_(0),
105 weak_ptr_factory_(this) {
106 CreateNamespace();
109 void TestWebGraphicsContext3D::CreateNamespace() {
110 if (attributes_.shareResources) {
111 base::AutoLock lock(g_shared_namespace_lock.Get());
112 if (shared_namespace_) {
113 namespace_ = shared_namespace_;
114 } else {
115 namespace_ = new Namespace;
116 shared_namespace_ = namespace_.get();
118 } else {
119 namespace_ = new Namespace;
123 TestWebGraphicsContext3D::~TestWebGraphicsContext3D() {
124 for (size_t i = 0; i < sync_point_callbacks_.size(); ++i) {
125 if (sync_point_callbacks_[i] != NULL)
126 delete sync_point_callbacks_[i];
128 base::AutoLock lock(g_shared_namespace_lock.Get());
129 namespace_ = NULL;
132 bool TestWebGraphicsContext3D::makeContextCurrent() {
133 if (times_make_current_succeeds_ >= 0) {
134 if (!times_make_current_succeeds_) {
135 loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
136 GL_INNOCENT_CONTEXT_RESET_ARB);
138 --times_make_current_succeeds_;
140 return !context_lost_;
143 int TestWebGraphicsContext3D::width() {
144 return width_;
147 int TestWebGraphicsContext3D::height() {
148 return height_;
151 void TestWebGraphicsContext3D::reshapeWithScaleFactor(
152 int width, int height, float scale_factor) {
153 width_ = width;
154 height_ = height;
157 bool TestWebGraphicsContext3D::isContextLost() {
158 return context_lost_;
161 WGC3Denum TestWebGraphicsContext3D::getGraphicsResetStatusARB() {
162 return context_lost_ ? GL_UNKNOWN_CONTEXT_RESET_ARB : GL_NO_ERROR;
165 WGC3Denum TestWebGraphicsContext3D::checkFramebufferStatus(
166 WGC3Denum target) {
167 if (context_lost_)
168 return GL_FRAMEBUFFER_UNDEFINED_OES;
169 return GL_FRAMEBUFFER_COMPLETE;
172 WebGraphicsContext3D::Attributes
173 TestWebGraphicsContext3D::getContextAttributes() {
174 return attributes_;
177 WebKit::WebString TestWebGraphicsContext3D::getString(WGC3Denum name) {
178 std::string string;
180 if (support_swapbuffers_complete_callback_)
181 string += "GL_CHROMIUM_swapbuffers_complete_callback";
183 if (name == GL_EXTENSIONS) {
184 if (have_extension_io_surface_)
185 string += " GL_CHROMIUM_iosurface GL_ARB_texture_rectangle";
186 if (have_extension_egl_image_)
187 string += " GL_OES_EGL_image_external";
190 return WebKit::WebString::fromUTF8(string.c_str());
193 WGC3Dint TestWebGraphicsContext3D::getUniformLocation(
194 WebGLId program,
195 const WGC3Dchar* name) {
196 return 0;
199 WGC3Dsizeiptr TestWebGraphicsContext3D::getVertexAttribOffset(
200 WGC3Duint index,
201 WGC3Denum pname) {
202 return 0;
205 WGC3Dboolean TestWebGraphicsContext3D::isBuffer(
206 WebGLId buffer) {
207 return false;
210 WGC3Dboolean TestWebGraphicsContext3D::isEnabled(
211 WGC3Denum cap) {
212 return false;
215 WGC3Dboolean TestWebGraphicsContext3D::isFramebuffer(
216 WebGLId framebuffer) {
217 return false;
220 WGC3Dboolean TestWebGraphicsContext3D::isProgram(
221 WebGLId program) {
222 return false;
225 WGC3Dboolean TestWebGraphicsContext3D::isRenderbuffer(
226 WebGLId renderbuffer) {
227 return false;
230 WGC3Dboolean TestWebGraphicsContext3D::isShader(
231 WebGLId shader) {
232 return false;
235 WGC3Dboolean TestWebGraphicsContext3D::isTexture(
236 WebGLId texture) {
237 return false;
240 WebGLId TestWebGraphicsContext3D::createBuffer() {
241 return NextBufferId();
244 void TestWebGraphicsContext3D::deleteBuffer(WebGLId id) {
245 base::AutoLock lock(namespace_->lock);
246 unsigned context_id = id >> 17;
247 unsigned buffer_id = id & 0x1ffff;
248 DCHECK(buffer_id && buffer_id < namespace_->next_buffer_id);
249 DCHECK_EQ(context_id, context_id_);
252 WebGLId TestWebGraphicsContext3D::createFramebuffer() {
253 return kFramebufferId | context_id_ << 16;
256 void TestWebGraphicsContext3D::deleteFramebuffer(WebGLId id) {
257 DCHECK_EQ(kFramebufferId | context_id_ << 16, id);
260 WebGLId TestWebGraphicsContext3D::createProgram() {
261 return kProgramId | context_id_ << 16;
264 void TestWebGraphicsContext3D::deleteProgram(WebGLId id) {
265 DCHECK_EQ(kProgramId | context_id_ << 16, id);
268 WebGLId TestWebGraphicsContext3D::createRenderbuffer() {
269 return kRenderbufferId | context_id_ << 16;
272 void TestWebGraphicsContext3D::deleteRenderbuffer(WebGLId id) {
273 DCHECK_EQ(kRenderbufferId | context_id_ << 16, id);
276 WebGLId TestWebGraphicsContext3D::createShader(WGC3Denum) {
277 return kShaderId | context_id_ << 16;
280 void TestWebGraphicsContext3D::deleteShader(WebGLId id) {
281 DCHECK_EQ(kShaderId | context_id_ << 16, id);
284 WebGLId TestWebGraphicsContext3D::createTexture() {
285 WebGLId texture_id = NextTextureId();
286 DCHECK_NE(texture_id, kExternalTextureId);
287 base::AutoLock lock(namespace_->lock);
288 namespace_->textures.push_back(texture_id);
289 return texture_id;
292 void TestWebGraphicsContext3D::deleteTexture(WebGLId texture_id) {
293 base::AutoLock lock(namespace_->lock);
294 std::vector<WebKit::WebGLId>& textures = namespace_->textures;
295 DCHECK(std::find(textures.begin(), textures.end(), texture_id) !=
296 textures.end());
297 textures.erase(std::find(textures.begin(), textures.end(), texture_id));
300 void TestWebGraphicsContext3D::attachShader(WebGLId program, WebGLId shader) {
301 DCHECK_EQ(kProgramId | context_id_ << 16, program);
302 DCHECK_EQ(kShaderId | context_id_ << 16, shader);
305 void TestWebGraphicsContext3D::useProgram(WebGLId program) {
306 if (!program)
307 return;
308 DCHECK_EQ(kProgramId | context_id_ << 16, program);
311 void TestWebGraphicsContext3D::bindFramebuffer(
312 WGC3Denum target, WebGLId framebuffer) {
313 if (!framebuffer)
314 return;
315 DCHECK_EQ(kFramebufferId | context_id_ << 16, framebuffer);
318 void TestWebGraphicsContext3D::bindRenderbuffer(
319 WGC3Denum target, WebGLId renderbuffer) {
320 if (!renderbuffer)
321 return;
322 DCHECK_EQ(kRenderbufferId | context_id_ << 16, renderbuffer);
325 void TestWebGraphicsContext3D::bindTexture(
326 WGC3Denum target, WebGLId texture_id) {
327 if (times_bind_texture_succeeds_ >= 0) {
328 if (!times_bind_texture_succeeds_) {
329 loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
330 GL_INNOCENT_CONTEXT_RESET_ARB);
332 --times_bind_texture_succeeds_;
335 if (!texture_id)
336 return;
337 if (texture_id == kExternalTextureId)
338 return;
339 base::AutoLock lock(namespace_->lock);
340 std::vector<WebKit::WebGLId>& textures = namespace_->textures;
341 DCHECK(std::find(textures.begin(), textures.end(), texture_id) !=
342 textures.end());
343 used_textures_.insert(texture_id);
346 void TestWebGraphicsContext3D::endQueryEXT(WGC3Denum target) {
347 if (times_end_query_succeeds_ >= 0) {
348 if (!times_end_query_succeeds_) {
349 loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
350 GL_INNOCENT_CONTEXT_RESET_ARB);
352 --times_end_query_succeeds_;
356 void TestWebGraphicsContext3D::getQueryObjectuivEXT(
357 WebGLId query,
358 WGC3Denum pname,
359 WGC3Duint* params) {
360 // If the context is lost, behave as if result is available.
361 if (pname == GL_QUERY_RESULT_AVAILABLE_EXT)
362 *params = 1;
365 void TestWebGraphicsContext3D::getIntegerv(
366 WGC3Denum pname,
367 WebKit::WGC3Dint* value) {
368 if (pname == GL_MAX_TEXTURE_SIZE)
369 *value = max_texture_size_;
370 else if (pname == GL_ACTIVE_TEXTURE)
371 *value = GL_TEXTURE0;
374 void TestWebGraphicsContext3D::genMailboxCHROMIUM(WebKit::WGC3Dbyte* mailbox) {
375 if (times_gen_mailbox_succeeds_ >= 0) {
376 if (!times_gen_mailbox_succeeds_) {
377 loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
378 GL_INNOCENT_CONTEXT_RESET_ARB);
380 --times_gen_mailbox_succeeds_;
382 if (context_lost_) {
383 memset(mailbox, 0, 64);
384 return;
387 static char mailbox_name1 = '1';
388 static char mailbox_name2 = '1';
389 mailbox[0] = mailbox_name1;
390 mailbox[1] = mailbox_name2;
391 mailbox[2] = '\0';
392 if (++mailbox_name1 == 0) {
393 mailbox_name1 = '1';
394 ++mailbox_name2;
398 void TestWebGraphicsContext3D::setContextLostCallback(
399 WebGraphicsContextLostCallback* callback) {
400 context_lost_callback_ = callback;
403 void TestWebGraphicsContext3D::loseContextCHROMIUM(WGC3Denum current,
404 WGC3Denum other) {
405 if (context_lost_)
406 return;
407 context_lost_ = true;
408 if (context_lost_callback_)
409 context_lost_callback_->onContextLost();
411 for (size_t i = 0; i < shared_contexts_.size(); ++i)
412 shared_contexts_[i]->loseContextCHROMIUM(current, other);
413 shared_contexts_.clear();
416 void TestWebGraphicsContext3D::signalSyncPoint(
417 unsigned sync_point,
418 WebGraphicsSyncPointCallback* callback) {
419 sync_point_callbacks_.push_back(callback);
422 void TestWebGraphicsContext3D::signalQuery(
423 WebKit::WebGLId query,
424 WebGraphicsSyncPointCallback* callback) {
425 sync_point_callbacks_.push_back(callback);
428 void TestWebGraphicsContext3D::setSwapBuffersCompleteCallbackCHROMIUM(
429 WebGraphicsSwapBuffersCompleteCallbackCHROMIUM* callback) {
430 if (support_swapbuffers_complete_callback_)
431 swap_buffers_callback_ = callback;
434 void TestWebGraphicsContext3D::prepareTexture() {
435 if (swap_buffers_callback_) {
436 base::MessageLoop::current()->PostTask(
437 FROM_HERE, base::Bind(&TestWebGraphicsContext3D::SwapBuffersComplete,
438 weak_ptr_factory_.GetWeakPtr()));
440 CallAllSyncPointCallbacks();
443 void TestWebGraphicsContext3D::finish() {
444 CallAllSyncPointCallbacks();
447 void TestWebGraphicsContext3D::flush() {
448 CallAllSyncPointCallbacks();
451 static void CallAndDestroy(
452 WebKit::WebGraphicsContext3D::WebGraphicsSyncPointCallback* callback) {
453 if (!callback)
454 return;
455 callback->onSyncPointReached();
456 delete callback;
459 void TestWebGraphicsContext3D::CallAllSyncPointCallbacks() {
460 for (size_t i = 0; i < sync_point_callbacks_.size(); ++i) {
461 base::MessageLoop::current()->PostTask(
462 FROM_HERE,
463 base::Bind(&CallAndDestroy,
464 sync_point_callbacks_[i]));
466 sync_point_callbacks_.clear();
469 void TestWebGraphicsContext3D::SwapBuffersComplete() {
470 if (swap_buffers_callback_)
471 swap_buffers_callback_->onSwapBuffersComplete();
474 void TestWebGraphicsContext3D::bindBuffer(WebKit::WGC3Denum target,
475 WebKit::WebGLId buffer) {
476 bound_buffer_ = buffer;
477 if (!bound_buffer_)
478 return;
479 unsigned context_id = buffer >> 17;
480 unsigned buffer_id = buffer & 0x1ffff;
481 base::AutoLock lock(namespace_->lock);
482 DCHECK(buffer_id && buffer_id < namespace_->next_buffer_id);
483 DCHECK_EQ(context_id, context_id_);
485 ScopedPtrHashMap<unsigned, Buffer>& buffers = namespace_->buffers;
486 if (buffers.count(bound_buffer_) == 0)
487 buffers.set(bound_buffer_, make_scoped_ptr(new Buffer).Pass());
489 buffers.get(bound_buffer_)->target = target;
492 void TestWebGraphicsContext3D::bufferData(WebKit::WGC3Denum target,
493 WebKit::WGC3Dsizeiptr size,
494 const void* data,
495 WebKit::WGC3Denum usage) {
496 base::AutoLock lock(namespace_->lock);
497 ScopedPtrHashMap<unsigned, Buffer>& buffers = namespace_->buffers;
498 DCHECK_GT(buffers.count(bound_buffer_), 0u);
499 DCHECK_EQ(target, buffers.get(bound_buffer_)->target);
500 if (context_lost_) {
501 buffers.get(bound_buffer_)->pixels.reset();
502 return;
504 buffers.get(bound_buffer_)->pixels.reset(new uint8[size]);
505 if (data != NULL)
506 memcpy(buffers.get(bound_buffer_)->pixels.get(), data, size);
509 void* TestWebGraphicsContext3D::mapBufferCHROMIUM(WebKit::WGC3Denum target,
510 WebKit::WGC3Denum access) {
511 base::AutoLock lock(namespace_->lock);
512 ScopedPtrHashMap<unsigned, Buffer>& buffers = namespace_->buffers;
513 DCHECK_GT(buffers.count(bound_buffer_), 0u);
514 DCHECK_EQ(target, buffers.get(bound_buffer_)->target);
515 if (times_map_buffer_chromium_succeeds_ >= 0) {
516 if (!times_map_buffer_chromium_succeeds_) {
517 return NULL;
519 --times_map_buffer_chromium_succeeds_;
521 return buffers.get(bound_buffer_)->pixels.get();
524 WebKit::WGC3Dboolean TestWebGraphicsContext3D::unmapBufferCHROMIUM(
525 WebKit::WGC3Denum target) {
526 base::AutoLock lock(namespace_->lock);
527 ScopedPtrHashMap<unsigned, Buffer>& buffers = namespace_->buffers;
528 DCHECK_GT(buffers.count(bound_buffer_), 0u);
529 DCHECK_EQ(target, buffers.get(bound_buffer_)->target);
530 buffers.get(bound_buffer_)->pixels.reset();
531 return true;
534 WebKit::WGC3Duint TestWebGraphicsContext3D::createImageCHROMIUM(
535 WebKit::WGC3Dsizei width, WebKit::WGC3Dsizei height,
536 WebKit::WGC3Denum internalformat) {
537 DCHECK_EQ(GL_RGBA8_OES, static_cast<int>(internalformat));
538 WebKit::WGC3Duint image_id = NextImageId();
539 base::AutoLock lock(namespace_->lock);
540 ScopedPtrHashMap<unsigned, Image>& images = namespace_->images;
541 images.set(image_id, make_scoped_ptr(new Image).Pass());
542 images.get(image_id)->pixels.reset(new uint8[width * height * 4]);
543 return image_id;
546 void TestWebGraphicsContext3D::destroyImageCHROMIUM(
547 WebKit::WGC3Duint id) {
548 base::AutoLock lock(namespace_->lock);
549 unsigned context_id = id >> 17;
550 unsigned image_id = id & 0x1ffff;
551 DCHECK(image_id && image_id < namespace_->next_image_id);
552 DCHECK_EQ(context_id, context_id_);
555 void TestWebGraphicsContext3D::getImageParameterivCHROMIUM(
556 WebKit::WGC3Duint image_id,
557 WebKit::WGC3Denum pname,
558 WebKit::WGC3Dint* params) {
559 base::AutoLock lock(namespace_->lock);
560 DCHECK_GT(namespace_->images.count(image_id), 0u);
561 DCHECK_EQ(GL_IMAGE_ROWBYTES_CHROMIUM, static_cast<int>(pname));
562 *params = 0;
565 void* TestWebGraphicsContext3D::mapImageCHROMIUM(WebKit::WGC3Duint image_id,
566 WebKit::WGC3Denum access) {
567 base::AutoLock lock(namespace_->lock);
568 ScopedPtrHashMap<unsigned, Image>& images = namespace_->images;
569 DCHECK_GT(images.count(image_id), 0u);
570 if (times_map_image_chromium_succeeds_ >= 0) {
571 if (!times_map_image_chromium_succeeds_) {
572 return NULL;
574 --times_map_image_chromium_succeeds_;
576 return images.get(image_id)->pixels.get();
579 void TestWebGraphicsContext3D::unmapImageCHROMIUM(
580 WebKit::WGC3Duint image_id) {
581 base::AutoLock lock(namespace_->lock);
582 DCHECK_GT(namespace_->images.count(image_id), 0u);
585 size_t TestWebGraphicsContext3D::NumTextures() const {
586 base::AutoLock lock(namespace_->lock);
587 return namespace_->textures.size();
590 WebKit::WebGLId TestWebGraphicsContext3D::TextureAt(int i) const {
591 base::AutoLock lock(namespace_->lock);
592 return namespace_->textures[i];
595 WebGLId TestWebGraphicsContext3D::NextTextureId() {
596 base::AutoLock lock(namespace_->lock);
597 WebGLId texture_id = namespace_->next_texture_id++;
598 DCHECK(texture_id < (1 << 16));
599 texture_id |= context_id_ << 16;
600 return texture_id;
603 WebGLId TestWebGraphicsContext3D::NextBufferId() {
604 base::AutoLock lock(namespace_->lock);
605 WebGLId buffer_id = namespace_->next_buffer_id++;
606 DCHECK(buffer_id < (1 << 17));
607 buffer_id |= context_id_ << 17;
608 return buffer_id;
611 WebKit::WGC3Duint TestWebGraphicsContext3D::NextImageId() {
612 base::AutoLock lock(namespace_->lock);
613 WGC3Duint image_id = namespace_->next_image_id++;
614 DCHECK(image_id < (1 << 17));
615 image_id |= context_id_ << 17;
616 return image_id;
619 TestWebGraphicsContext3D::Buffer::Buffer() : target(0) {}
621 TestWebGraphicsContext3D::Buffer::~Buffer() {}
623 TestWebGraphicsContext3D::Image::Image() {}
625 TestWebGraphicsContext3D::Image::~Image() {}
627 } // namespace cc