1 // Copyright 2011 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/logging.h"
12 #include "base/message_loop.h"
13 #include "gpu/GLES2/gl2extchromium.h"
14 #include "testing/gtest/include/gtest/gtest.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
;
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 TestWebGraphicsContext3D::TestWebGraphicsContext3D()
39 : FakeWebGraphicsContext3D(),
40 context_id_(s_context_id
++),
43 have_extension_io_surface_(false),
44 have_extension_egl_image_(false),
45 times_make_current_succeeds_(-1),
46 times_bind_texture_succeeds_(-1),
47 times_end_query_succeeds_(-1),
49 context_lost_callback_(NULL
),
50 swap_buffers_callback_(NULL
),
51 max_texture_size_(1024),
55 weak_ptr_factory_(this) {
58 TestWebGraphicsContext3D::TestWebGraphicsContext3D(
59 const WebGraphicsContext3D::Attributes
& attributes
)
60 : FakeWebGraphicsContext3D(),
61 context_id_(s_context_id
++),
64 attributes_(attributes
),
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),
71 context_lost_callback_(NULL
),
72 swap_buffers_callback_(NULL
),
73 max_texture_size_(1024),
77 weak_ptr_factory_(this) {
80 TestWebGraphicsContext3D::~TestWebGraphicsContext3D() {
81 for (size_t i
= 0; i
< sync_point_callbacks_
.size(); ++i
) {
82 if (sync_point_callbacks_
[i
] != NULL
)
83 delete sync_point_callbacks_
[i
];
87 bool TestWebGraphicsContext3D::makeContextCurrent() {
88 if (times_make_current_succeeds_
>= 0) {
89 if (!times_make_current_succeeds_
) {
90 loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
91 GL_INNOCENT_CONTEXT_RESET_ARB
);
93 --times_make_current_succeeds_
;
95 return !context_lost_
;
98 int TestWebGraphicsContext3D::width() {
102 int TestWebGraphicsContext3D::height() {
106 void TestWebGraphicsContext3D::reshapeWithScaleFactor(
107 int width
, int height
, float scale_factor
) {
112 bool TestWebGraphicsContext3D::isContextLost() {
113 return context_lost_
;
116 WGC3Denum
TestWebGraphicsContext3D::getGraphicsResetStatusARB() {
117 return context_lost_
? GL_UNKNOWN_CONTEXT_RESET_ARB
: GL_NO_ERROR
;
120 WGC3Denum
TestWebGraphicsContext3D::checkFramebufferStatus(
123 return GL_FRAMEBUFFER_UNDEFINED_OES
;
124 return GL_FRAMEBUFFER_COMPLETE
;
127 WebGraphicsContext3D::Attributes
128 TestWebGraphicsContext3D::getContextAttributes() {
132 WebKit::WebString
TestWebGraphicsContext3D::getString(WGC3Denum name
) {
133 std::string
string("GL_CHROMIUM_swapbuffers_complete_callback");
135 if (name
== GL_EXTENSIONS
) {
136 if (have_extension_io_surface_
)
137 string
+= " GL_CHROMIUM_iosurface GL_ARB_texture_rectangle";
138 if (have_extension_egl_image_
)
139 string
+= " GL_OES_EGL_image_external";
142 return WebKit::WebString::fromUTF8(string
.c_str());
145 WGC3Dint
TestWebGraphicsContext3D::getUniformLocation(
147 const WGC3Dchar
* name
) {
151 WGC3Dsizeiptr
TestWebGraphicsContext3D::getVertexAttribOffset(
157 WGC3Dboolean
TestWebGraphicsContext3D::isBuffer(
162 WGC3Dboolean
TestWebGraphicsContext3D::isEnabled(
167 WGC3Dboolean
TestWebGraphicsContext3D::isFramebuffer(
168 WebGLId framebuffer
) {
172 WGC3Dboolean
TestWebGraphicsContext3D::isProgram(
177 WGC3Dboolean
TestWebGraphicsContext3D::isRenderbuffer(
178 WebGLId renderbuffer
) {
182 WGC3Dboolean
TestWebGraphicsContext3D::isShader(
187 WGC3Dboolean
TestWebGraphicsContext3D::isTexture(
192 WebGLId
TestWebGraphicsContext3D::createBuffer() {
193 return NextBufferId();
196 void TestWebGraphicsContext3D::deleteBuffer(WebGLId id
) {
197 unsigned context_id
= id
>> 17;
198 unsigned buffer_id
= id
& 0x1ffff;
199 DCHECK(buffer_id
&& buffer_id
< next_buffer_id_
);
200 DCHECK_EQ(context_id
, context_id_
);
203 WebGLId
TestWebGraphicsContext3D::createFramebuffer() {
204 return kFramebufferId
| context_id_
<< 16;
207 void TestWebGraphicsContext3D::deleteFramebuffer(WebGLId id
) {
208 EXPECT_EQ(kFramebufferId
| context_id_
<< 16, id
);
211 WebGLId
TestWebGraphicsContext3D::createProgram() {
212 return kProgramId
| context_id_
<< 16;
215 void TestWebGraphicsContext3D::deleteProgram(WebGLId id
) {
216 EXPECT_EQ(kProgramId
| context_id_
<< 16, id
);
219 WebGLId
TestWebGraphicsContext3D::createRenderbuffer() {
220 return kRenderbufferId
| context_id_
<< 16;
223 void TestWebGraphicsContext3D::deleteRenderbuffer(WebGLId id
) {
224 EXPECT_EQ(kRenderbufferId
| context_id_
<< 16, id
);
227 WebGLId
TestWebGraphicsContext3D::createShader(WGC3Denum
) {
228 return kShaderId
| context_id_
<< 16;
231 void TestWebGraphicsContext3D::deleteShader(WebGLId id
) {
232 EXPECT_EQ(kShaderId
| context_id_
<< 16, id
);
235 WebGLId
TestWebGraphicsContext3D::createTexture() {
236 WebGLId texture_id
= NextTextureId();
237 DCHECK_NE(texture_id
, kExternalTextureId
);
238 textures_
.push_back(texture_id
);
242 void TestWebGraphicsContext3D::deleteTexture(WebGLId texture_id
) {
243 DCHECK(std::find(textures_
.begin(), textures_
.end(), texture_id
) !=
245 textures_
.erase(std::find(textures_
.begin(), textures_
.end(), texture_id
));
248 void TestWebGraphicsContext3D::attachShader(WebGLId program
, WebGLId shader
) {
249 EXPECT_EQ(kProgramId
| context_id_
<< 16, program
);
250 EXPECT_EQ(kShaderId
| context_id_
<< 16, shader
);
253 void TestWebGraphicsContext3D::useProgram(WebGLId program
) {
256 EXPECT_EQ(kProgramId
| context_id_
<< 16, program
);
259 void TestWebGraphicsContext3D::bindFramebuffer(
260 WGC3Denum target
, WebGLId framebuffer
) {
263 EXPECT_EQ(kFramebufferId
| context_id_
<< 16, framebuffer
);
266 void TestWebGraphicsContext3D::bindRenderbuffer(
267 WGC3Denum target
, WebGLId renderbuffer
) {
270 EXPECT_EQ(kRenderbufferId
| context_id_
<< 16, renderbuffer
);
273 void TestWebGraphicsContext3D::bindTexture(
274 WGC3Denum target
, WebGLId texture_id
) {
275 if (times_bind_texture_succeeds_
>= 0) {
276 if (!times_bind_texture_succeeds_
) {
277 loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
278 GL_INNOCENT_CONTEXT_RESET_ARB
);
280 --times_bind_texture_succeeds_
;
285 if (texture_id
== kExternalTextureId
)
287 DCHECK(std::find(textures_
.begin(), textures_
.end(), texture_id
) !=
289 used_textures_
.insert(texture_id
);
292 void TestWebGraphicsContext3D::endQueryEXT(WGC3Denum target
) {
293 if (times_end_query_succeeds_
>= 0) {
294 if (!times_end_query_succeeds_
) {
295 loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
296 GL_INNOCENT_CONTEXT_RESET_ARB
);
298 --times_end_query_succeeds_
;
302 void TestWebGraphicsContext3D::getQueryObjectuivEXT(
306 // If the context is lost, behave as if result is available.
307 if (pname
== GL_QUERY_RESULT_AVAILABLE_EXT
)
311 void TestWebGraphicsContext3D::getIntegerv(
313 WebKit::WGC3Dint
* value
) {
314 if (pname
== GL_MAX_TEXTURE_SIZE
)
315 *value
= max_texture_size_
;
318 void TestWebGraphicsContext3D::genMailboxCHROMIUM(WebKit::WGC3Dbyte
* mailbox
) {
319 static char mailbox_name1
= '1';
320 static char mailbox_name2
= '1';
321 mailbox
[0] = mailbox_name1
;
322 mailbox
[1] = mailbox_name2
;
324 if (++mailbox_name1
== 0) {
330 void TestWebGraphicsContext3D::setContextLostCallback(
331 WebGraphicsContextLostCallback
* callback
) {
332 context_lost_callback_
= callback
;
335 void TestWebGraphicsContext3D::loseContextCHROMIUM(WGC3Denum current
,
339 context_lost_
= true;
340 if (context_lost_callback_
)
341 context_lost_callback_
->onContextLost();
343 for (size_t i
= 0; i
< shared_contexts_
.size(); ++i
)
344 shared_contexts_
[i
]->loseContextCHROMIUM(current
, other
);
345 shared_contexts_
.clear();
348 void TestWebGraphicsContext3D::signalSyncPoint(
350 WebGraphicsSyncPointCallback
* callback
) {
351 sync_point_callbacks_
.push_back(callback
);
354 void TestWebGraphicsContext3D::setSwapBuffersCompleteCallbackCHROMIUM(
355 WebGraphicsSwapBuffersCompleteCallbackCHROMIUM
* callback
) {
356 swap_buffers_callback_
= callback
;
359 void TestWebGraphicsContext3D::prepareTexture() {
360 if (swap_buffers_callback_
) {
361 base::MessageLoop::current()->PostTask(
362 FROM_HERE
, base::Bind(&TestWebGraphicsContext3D::SwapBuffersComplete
,
363 weak_ptr_factory_
.GetWeakPtr()));
365 CallAllSyncPointCallbacks();
368 void TestWebGraphicsContext3D::finish() {
369 CallAllSyncPointCallbacks();
372 void TestWebGraphicsContext3D::flush() {
373 CallAllSyncPointCallbacks();
376 static void CallAndDestroy(
377 WebKit::WebGraphicsContext3D::WebGraphicsSyncPointCallback
* callback
) {
380 callback
->onSyncPointReached();
384 void TestWebGraphicsContext3D::CallAllSyncPointCallbacks() {
385 for (size_t i
= 0; i
< sync_point_callbacks_
.size(); ++i
) {
386 base::MessageLoop::current()->PostTask(
388 base::Bind(&CallAndDestroy
,
389 sync_point_callbacks_
[i
]));
391 sync_point_callbacks_
.clear();
394 void TestWebGraphicsContext3D::SwapBuffersComplete() {
395 if (swap_buffers_callback_
)
396 swap_buffers_callback_
->onSwapBuffersComplete();
399 void TestWebGraphicsContext3D::bindBuffer(WebKit::WGC3Denum target
,
400 WebKit::WebGLId buffer
) {
401 bound_buffer_
= buffer
;
404 unsigned context_id
= buffer
>> 17;
405 unsigned buffer_id
= buffer
& 0x1ffff;
406 DCHECK(buffer_id
&& buffer_id
< next_buffer_id_
);
407 DCHECK_EQ(context_id
, context_id_
);
409 if (buffers_
.count(bound_buffer_
) == 0)
410 buffers_
.set(bound_buffer_
, make_scoped_ptr(new Buffer
).Pass());
412 buffers_
.get(bound_buffer_
)->target
= target
;
415 void TestWebGraphicsContext3D::bufferData(WebKit::WGC3Denum target
,
416 WebKit::WGC3Dsizeiptr size
,
418 WebKit::WGC3Denum usage
) {
419 DCHECK_GT(buffers_
.count(bound_buffer_
), 0u);
420 DCHECK_EQ(target
, buffers_
.get(bound_buffer_
)->target
);
422 buffers_
.get(bound_buffer_
)->pixels
.reset();
425 buffers_
.get(bound_buffer_
)->pixels
.reset(new uint8
[size
]);
427 memcpy(buffers_
.get(bound_buffer_
)->pixels
.get(), data
, size
);
430 void* TestWebGraphicsContext3D::mapBufferCHROMIUM(WebKit::WGC3Denum target
,
431 WebKit::WGC3Denum access
) {
432 DCHECK_GT(buffers_
.count(bound_buffer_
), 0u);
433 DCHECK_EQ(target
, buffers_
.get(bound_buffer_
)->target
);
434 return buffers_
.get(bound_buffer_
)->pixels
.get();
437 WebKit::WGC3Dboolean
TestWebGraphicsContext3D::unmapBufferCHROMIUM(
438 WebKit::WGC3Denum target
) {
439 DCHECK_GT(buffers_
.count(bound_buffer_
), 0u);
440 DCHECK_EQ(target
, buffers_
.get(bound_buffer_
)->target
);
441 buffers_
.get(bound_buffer_
)->pixels
.reset();
445 WebGLId
TestWebGraphicsContext3D::NextTextureId() {
446 WebGLId texture_id
= next_texture_id_
++;
447 DCHECK(texture_id
< (1 << 16));
448 texture_id
|= context_id_
<< 16;
452 WebGLId
TestWebGraphicsContext3D::NextBufferId() {
453 WebGLId buffer_id
= next_buffer_id_
++;
454 DCHECK(buffer_id
< (1 << 17));
455 buffer_id
|= context_id_
<< 17;
459 TestWebGraphicsContext3D::Buffer::Buffer() : target(0) {}
461 TestWebGraphicsContext3D::Buffer::~Buffer() {}