cc: Added inline to Tile::IsReadyToDraw
[chromium-blink-merge.git] / cc / debug / test_web_graphics_context_3d.cc
blob04027aedab161eb8b2ee7c4ab1972c41e2ead9da
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 times_make_current_succeeds_(-1),
65 times_bind_texture_succeeds_(-1),
66 times_end_query_succeeds_(-1),
67 times_gen_mailbox_succeeds_(-1),
68 context_lost_(false),
69 times_map_image_chromium_succeeds_(-1),
70 times_map_buffer_chromium_succeeds_(-1),
71 context_lost_callback_(NULL),
72 swap_buffers_callback_(NULL),
73 max_texture_size_(2048),
74 width_(0),
75 height_(0),
76 bound_buffer_(0),
77 weak_ptr_factory_(this) {
78 CreateNamespace();
79 test_capabilities_.swapbuffers_complete_callback = true;
82 TestWebGraphicsContext3D::TestWebGraphicsContext3D(
83 const WebGraphicsContext3D::Attributes& attributes)
84 : FakeWebGraphicsContext3D(),
85 context_id_(s_context_id++),
86 attributes_(attributes),
87 times_make_current_succeeds_(-1),
88 times_bind_texture_succeeds_(-1),
89 times_end_query_succeeds_(-1),
90 times_gen_mailbox_succeeds_(-1),
91 context_lost_(false),
92 times_map_image_chromium_succeeds_(-1),
93 times_map_buffer_chromium_succeeds_(-1),
94 context_lost_callback_(NULL),
95 swap_buffers_callback_(NULL),
96 max_texture_size_(2048),
97 width_(0),
98 height_(0),
99 bound_buffer_(0),
100 weak_ptr_factory_(this) {
101 CreateNamespace();
102 test_capabilities_.swapbuffers_complete_callback = true;
105 void TestWebGraphicsContext3D::CreateNamespace() {
106 if (attributes_.shareResources) {
107 base::AutoLock lock(g_shared_namespace_lock.Get());
108 if (shared_namespace_) {
109 namespace_ = shared_namespace_;
110 } else {
111 namespace_ = new Namespace;
112 shared_namespace_ = namespace_.get();
114 } else {
115 namespace_ = new Namespace;
119 TestWebGraphicsContext3D::~TestWebGraphicsContext3D() {
120 for (size_t i = 0; i < sync_point_callbacks_.size(); ++i) {
121 if (sync_point_callbacks_[i] != NULL)
122 delete sync_point_callbacks_[i];
124 base::AutoLock lock(g_shared_namespace_lock.Get());
125 namespace_ = NULL;
128 bool TestWebGraphicsContext3D::makeContextCurrent() {
129 if (times_make_current_succeeds_ >= 0) {
130 if (!times_make_current_succeeds_) {
131 loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
132 GL_INNOCENT_CONTEXT_RESET_ARB);
134 --times_make_current_succeeds_;
136 return !context_lost_;
139 int TestWebGraphicsContext3D::width() {
140 return width_;
143 int TestWebGraphicsContext3D::height() {
144 return height_;
147 void TestWebGraphicsContext3D::reshapeWithScaleFactor(
148 int width, int height, float scale_factor) {
149 width_ = width;
150 height_ = height;
153 bool TestWebGraphicsContext3D::isContextLost() {
154 return context_lost_;
157 WGC3Denum TestWebGraphicsContext3D::getGraphicsResetStatusARB() {
158 return context_lost_ ? GL_UNKNOWN_CONTEXT_RESET_ARB : GL_NO_ERROR;
161 WGC3Denum TestWebGraphicsContext3D::checkFramebufferStatus(
162 WGC3Denum target) {
163 if (context_lost_)
164 return GL_FRAMEBUFFER_UNDEFINED_OES;
165 return GL_FRAMEBUFFER_COMPLETE;
168 WebGraphicsContext3D::Attributes
169 TestWebGraphicsContext3D::getContextAttributes() {
170 return attributes_;
173 WebKit::WebString TestWebGraphicsContext3D::getString(WGC3Denum name) {
174 return WebKit::WebString();
177 WGC3Dint TestWebGraphicsContext3D::getUniformLocation(
178 WebGLId program,
179 const WGC3Dchar* name) {
180 return 0;
183 WGC3Dsizeiptr TestWebGraphicsContext3D::getVertexAttribOffset(
184 WGC3Duint index,
185 WGC3Denum pname) {
186 return 0;
189 WGC3Dboolean TestWebGraphicsContext3D::isBuffer(
190 WebGLId buffer) {
191 return false;
194 WGC3Dboolean TestWebGraphicsContext3D::isEnabled(
195 WGC3Denum cap) {
196 return false;
199 WGC3Dboolean TestWebGraphicsContext3D::isFramebuffer(
200 WebGLId framebuffer) {
201 return false;
204 WGC3Dboolean TestWebGraphicsContext3D::isProgram(
205 WebGLId program) {
206 return false;
209 WGC3Dboolean TestWebGraphicsContext3D::isRenderbuffer(
210 WebGLId renderbuffer) {
211 return false;
214 WGC3Dboolean TestWebGraphicsContext3D::isShader(
215 WebGLId shader) {
216 return false;
219 WGC3Dboolean TestWebGraphicsContext3D::isTexture(
220 WebGLId texture) {
221 return false;
224 WebGLId TestWebGraphicsContext3D::createBuffer() {
225 return NextBufferId();
228 void TestWebGraphicsContext3D::deleteBuffer(WebGLId id) {
229 base::AutoLock lock(namespace_->lock);
230 unsigned context_id = id >> 17;
231 unsigned buffer_id = id & 0x1ffff;
232 DCHECK(buffer_id && buffer_id < namespace_->next_buffer_id);
233 DCHECK_EQ(context_id, context_id_);
236 WebGLId TestWebGraphicsContext3D::createFramebuffer() {
237 return kFramebufferId | context_id_ << 16;
240 void TestWebGraphicsContext3D::deleteFramebuffer(WebGLId id) {
241 DCHECK_EQ(kFramebufferId | context_id_ << 16, id);
244 WebGLId TestWebGraphicsContext3D::createProgram() {
245 return kProgramId | context_id_ << 16;
248 void TestWebGraphicsContext3D::deleteProgram(WebGLId id) {
249 DCHECK_EQ(kProgramId | context_id_ << 16, id);
252 WebGLId TestWebGraphicsContext3D::createRenderbuffer() {
253 return kRenderbufferId | context_id_ << 16;
256 void TestWebGraphicsContext3D::deleteRenderbuffer(WebGLId id) {
257 DCHECK_EQ(kRenderbufferId | context_id_ << 16, id);
260 WebGLId TestWebGraphicsContext3D::createShader(WGC3Denum) {
261 return kShaderId | context_id_ << 16;
264 void TestWebGraphicsContext3D::deleteShader(WebGLId id) {
265 DCHECK_EQ(kShaderId | context_id_ << 16, id);
268 WebGLId TestWebGraphicsContext3D::createTexture() {
269 WebGLId texture_id = NextTextureId();
270 DCHECK_NE(texture_id, kExternalTextureId);
271 base::AutoLock lock(namespace_->lock);
272 namespace_->textures.push_back(texture_id);
273 return texture_id;
276 void TestWebGraphicsContext3D::deleteTexture(WebGLId texture_id) {
277 base::AutoLock lock(namespace_->lock);
278 std::vector<WebKit::WebGLId>& textures = namespace_->textures;
279 DCHECK(std::find(textures.begin(), textures.end(), texture_id) !=
280 textures.end());
281 textures.erase(std::find(textures.begin(), textures.end(), texture_id));
284 void TestWebGraphicsContext3D::attachShader(WebGLId program, WebGLId shader) {
285 DCHECK_EQ(kProgramId | context_id_ << 16, program);
286 DCHECK_EQ(kShaderId | context_id_ << 16, shader);
289 void TestWebGraphicsContext3D::useProgram(WebGLId program) {
290 if (!program)
291 return;
292 DCHECK_EQ(kProgramId | context_id_ << 16, program);
295 void TestWebGraphicsContext3D::bindFramebuffer(
296 WGC3Denum target, WebGLId framebuffer) {
297 if (!framebuffer)
298 return;
299 DCHECK_EQ(kFramebufferId | context_id_ << 16, framebuffer);
302 void TestWebGraphicsContext3D::bindRenderbuffer(
303 WGC3Denum target, WebGLId renderbuffer) {
304 if (!renderbuffer)
305 return;
306 DCHECK_EQ(kRenderbufferId | context_id_ << 16, renderbuffer);
309 void TestWebGraphicsContext3D::bindTexture(
310 WGC3Denum target, WebGLId texture_id) {
311 if (times_bind_texture_succeeds_ >= 0) {
312 if (!times_bind_texture_succeeds_) {
313 loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
314 GL_INNOCENT_CONTEXT_RESET_ARB);
316 --times_bind_texture_succeeds_;
319 if (!texture_id)
320 return;
321 if (texture_id == kExternalTextureId)
322 return;
323 base::AutoLock lock(namespace_->lock);
324 std::vector<WebKit::WebGLId>& textures = namespace_->textures;
325 DCHECK(std::find(textures.begin(), textures.end(), texture_id) !=
326 textures.end());
327 used_textures_.insert(texture_id);
330 void TestWebGraphicsContext3D::endQueryEXT(WGC3Denum target) {
331 if (times_end_query_succeeds_ >= 0) {
332 if (!times_end_query_succeeds_) {
333 loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
334 GL_INNOCENT_CONTEXT_RESET_ARB);
336 --times_end_query_succeeds_;
340 void TestWebGraphicsContext3D::getQueryObjectuivEXT(
341 WebGLId query,
342 WGC3Denum pname,
343 WGC3Duint* params) {
344 // If the context is lost, behave as if result is available.
345 if (pname == GL_QUERY_RESULT_AVAILABLE_EXT)
346 *params = 1;
349 void TestWebGraphicsContext3D::getIntegerv(
350 WGC3Denum pname,
351 WebKit::WGC3Dint* value) {
352 if (pname == GL_MAX_TEXTURE_SIZE)
353 *value = max_texture_size_;
354 else if (pname == GL_ACTIVE_TEXTURE)
355 *value = GL_TEXTURE0;
358 void TestWebGraphicsContext3D::genMailboxCHROMIUM(WebKit::WGC3Dbyte* mailbox) {
359 if (times_gen_mailbox_succeeds_ >= 0) {
360 if (!times_gen_mailbox_succeeds_) {
361 loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
362 GL_INNOCENT_CONTEXT_RESET_ARB);
364 --times_gen_mailbox_succeeds_;
366 if (context_lost_) {
367 memset(mailbox, 0, 64);
368 return;
371 static char mailbox_name1 = '1';
372 static char mailbox_name2 = '1';
373 mailbox[0] = mailbox_name1;
374 mailbox[1] = mailbox_name2;
375 mailbox[2] = '\0';
376 if (++mailbox_name1 == 0) {
377 mailbox_name1 = '1';
378 ++mailbox_name2;
382 void TestWebGraphicsContext3D::setContextLostCallback(
383 WebGraphicsContextLostCallback* callback) {
384 context_lost_callback_ = callback;
387 void TestWebGraphicsContext3D::loseContextCHROMIUM(WGC3Denum current,
388 WGC3Denum other) {
389 if (context_lost_)
390 return;
391 context_lost_ = true;
392 if (context_lost_callback_)
393 context_lost_callback_->onContextLost();
395 for (size_t i = 0; i < shared_contexts_.size(); ++i)
396 shared_contexts_[i]->loseContextCHROMIUM(current, other);
397 shared_contexts_.clear();
400 void TestWebGraphicsContext3D::signalSyncPoint(
401 unsigned sync_point,
402 WebGraphicsSyncPointCallback* callback) {
403 sync_point_callbacks_.push_back(callback);
406 void TestWebGraphicsContext3D::signalQuery(
407 WebKit::WebGLId query,
408 WebGraphicsSyncPointCallback* callback) {
409 sync_point_callbacks_.push_back(callback);
412 void TestWebGraphicsContext3D::setSwapBuffersCompleteCallbackCHROMIUM(
413 WebGraphicsSwapBuffersCompleteCallbackCHROMIUM* callback) {
414 if (test_capabilities_.swapbuffers_complete_callback)
415 swap_buffers_callback_ = callback;
418 void TestWebGraphicsContext3D::prepareTexture() {
419 if (swap_buffers_callback_) {
420 base::MessageLoop::current()->PostTask(
421 FROM_HERE, base::Bind(&TestWebGraphicsContext3D::SwapBuffersComplete,
422 weak_ptr_factory_.GetWeakPtr()));
424 CallAllSyncPointCallbacks();
427 void TestWebGraphicsContext3D::finish() {
428 CallAllSyncPointCallbacks();
431 void TestWebGraphicsContext3D::flush() {
432 CallAllSyncPointCallbacks();
435 static void CallAndDestroy(
436 WebKit::WebGraphicsContext3D::WebGraphicsSyncPointCallback* callback) {
437 if (!callback)
438 return;
439 callback->onSyncPointReached();
440 delete callback;
443 void TestWebGraphicsContext3D::CallAllSyncPointCallbacks() {
444 for (size_t i = 0; i < sync_point_callbacks_.size(); ++i) {
445 base::MessageLoop::current()->PostTask(
446 FROM_HERE,
447 base::Bind(&CallAndDestroy,
448 sync_point_callbacks_[i]));
450 sync_point_callbacks_.clear();
453 void TestWebGraphicsContext3D::SwapBuffersComplete() {
454 if (swap_buffers_callback_)
455 swap_buffers_callback_->onSwapBuffersComplete();
458 void TestWebGraphicsContext3D::bindBuffer(WebKit::WGC3Denum target,
459 WebKit::WebGLId buffer) {
460 bound_buffer_ = buffer;
461 if (!bound_buffer_)
462 return;
463 unsigned context_id = buffer >> 17;
464 unsigned buffer_id = buffer & 0x1ffff;
465 base::AutoLock lock(namespace_->lock);
466 DCHECK(buffer_id && buffer_id < namespace_->next_buffer_id);
467 DCHECK_EQ(context_id, context_id_);
469 base::ScopedPtrHashMap<unsigned, Buffer>& buffers = namespace_->buffers;
470 if (buffers.count(bound_buffer_) == 0)
471 buffers.set(bound_buffer_, make_scoped_ptr(new Buffer).Pass());
473 buffers.get(bound_buffer_)->target = target;
476 void TestWebGraphicsContext3D::bufferData(WebKit::WGC3Denum target,
477 WebKit::WGC3Dsizeiptr size,
478 const void* data,
479 WebKit::WGC3Denum usage) {
480 base::AutoLock lock(namespace_->lock);
481 base::ScopedPtrHashMap<unsigned, Buffer>& buffers = namespace_->buffers;
482 DCHECK_GT(buffers.count(bound_buffer_), 0u);
483 DCHECK_EQ(target, buffers.get(bound_buffer_)->target);
484 if (context_lost_) {
485 buffers.get(bound_buffer_)->pixels.reset();
486 return;
488 buffers.get(bound_buffer_)->pixels.reset(new uint8[size]);
489 if (data != NULL)
490 memcpy(buffers.get(bound_buffer_)->pixels.get(), data, size);
493 void* TestWebGraphicsContext3D::mapBufferCHROMIUM(WebKit::WGC3Denum target,
494 WebKit::WGC3Denum access) {
495 base::AutoLock lock(namespace_->lock);
496 base::ScopedPtrHashMap<unsigned, Buffer>& buffers = namespace_->buffers;
497 DCHECK_GT(buffers.count(bound_buffer_), 0u);
498 DCHECK_EQ(target, buffers.get(bound_buffer_)->target);
499 if (times_map_buffer_chromium_succeeds_ >= 0) {
500 if (!times_map_buffer_chromium_succeeds_) {
501 return NULL;
503 --times_map_buffer_chromium_succeeds_;
505 return buffers.get(bound_buffer_)->pixels.get();
508 WebKit::WGC3Dboolean TestWebGraphicsContext3D::unmapBufferCHROMIUM(
509 WebKit::WGC3Denum target) {
510 base::AutoLock lock(namespace_->lock);
511 base::ScopedPtrHashMap<unsigned, Buffer>& buffers = namespace_->buffers;
512 DCHECK_GT(buffers.count(bound_buffer_), 0u);
513 DCHECK_EQ(target, buffers.get(bound_buffer_)->target);
514 buffers.get(bound_buffer_)->pixels.reset();
515 return true;
518 WebKit::WGC3Duint TestWebGraphicsContext3D::createImageCHROMIUM(
519 WebKit::WGC3Dsizei width, WebKit::WGC3Dsizei height,
520 WebKit::WGC3Denum internalformat) {
521 DCHECK_EQ(GL_RGBA8_OES, static_cast<int>(internalformat));
522 WebKit::WGC3Duint image_id = NextImageId();
523 base::AutoLock lock(namespace_->lock);
524 base::ScopedPtrHashMap<unsigned, Image>& images = namespace_->images;
525 images.set(image_id, make_scoped_ptr(new Image).Pass());
526 images.get(image_id)->pixels.reset(new uint8[width * height * 4]);
527 return image_id;
530 void TestWebGraphicsContext3D::destroyImageCHROMIUM(
531 WebKit::WGC3Duint id) {
532 base::AutoLock lock(namespace_->lock);
533 unsigned context_id = id >> 17;
534 unsigned image_id = id & 0x1ffff;
535 DCHECK(image_id && image_id < namespace_->next_image_id);
536 DCHECK_EQ(context_id, context_id_);
539 void TestWebGraphicsContext3D::getImageParameterivCHROMIUM(
540 WebKit::WGC3Duint image_id,
541 WebKit::WGC3Denum pname,
542 WebKit::WGC3Dint* params) {
543 base::AutoLock lock(namespace_->lock);
544 DCHECK_GT(namespace_->images.count(image_id), 0u);
545 DCHECK_EQ(GL_IMAGE_ROWBYTES_CHROMIUM, static_cast<int>(pname));
546 *params = 0;
549 void* TestWebGraphicsContext3D::mapImageCHROMIUM(WebKit::WGC3Duint image_id,
550 WebKit::WGC3Denum access) {
551 base::AutoLock lock(namespace_->lock);
552 base::ScopedPtrHashMap<unsigned, Image>& images = namespace_->images;
553 DCHECK_GT(images.count(image_id), 0u);
554 if (times_map_image_chromium_succeeds_ >= 0) {
555 if (!times_map_image_chromium_succeeds_) {
556 return NULL;
558 --times_map_image_chromium_succeeds_;
560 return images.get(image_id)->pixels.get();
563 void TestWebGraphicsContext3D::unmapImageCHROMIUM(
564 WebKit::WGC3Duint image_id) {
565 base::AutoLock lock(namespace_->lock);
566 DCHECK_GT(namespace_->images.count(image_id), 0u);
569 size_t TestWebGraphicsContext3D::NumTextures() const {
570 base::AutoLock lock(namespace_->lock);
571 return namespace_->textures.size();
574 WebKit::WebGLId TestWebGraphicsContext3D::TextureAt(int i) const {
575 base::AutoLock lock(namespace_->lock);
576 return namespace_->textures[i];
579 WebGLId TestWebGraphicsContext3D::NextTextureId() {
580 base::AutoLock lock(namespace_->lock);
581 WebGLId texture_id = namespace_->next_texture_id++;
582 DCHECK(texture_id < (1 << 16));
583 texture_id |= context_id_ << 16;
584 return texture_id;
587 WebGLId TestWebGraphicsContext3D::NextBufferId() {
588 base::AutoLock lock(namespace_->lock);
589 WebGLId buffer_id = namespace_->next_buffer_id++;
590 DCHECK(buffer_id < (1 << 17));
591 buffer_id |= context_id_ << 17;
592 return buffer_id;
595 WebKit::WGC3Duint TestWebGraphicsContext3D::NextImageId() {
596 base::AutoLock lock(namespace_->lock);
597 WGC3Duint image_id = namespace_->next_image_id++;
598 DCHECK(image_id < (1 << 17));
599 image_id |= context_id_ << 17;
600 return image_id;
603 TestWebGraphicsContext3D::Buffer::Buffer() : target(0) {}
605 TestWebGraphicsContext3D::Buffer::~Buffer() {}
607 TestWebGraphicsContext3D::Image::Image() {}
609 TestWebGraphicsContext3D::Image::~Image() {}
611 } // namespace cc