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. 4 5 #ifndef CC_TEST_TEST_WEB_GRAPHICS_CONTEXT_3D_H_ 6 #define CC_TEST_TEST_WEB_GRAPHICS_CONTEXT_3D_H_ 7 8 #include <vector> 9 10 #include "base/callback.h" 11 #include "base/compiler_specific.h" 12 #include "base/containers/hash_tables.h" 13 #include "base/containers/scoped_ptr_hash_map.h" 14 #include "base/memory/ref_counted.h" 15 #include "base/memory/scoped_ptr.h" 16 #include "base/memory/weak_ptr.h" 17 #include "base/stl_util.h" 18 #include "base/synchronization/lock.h" 19 #include "cc/output/context_provider.h" 20 #include "cc/test/ordered_texture_map.h" 21 #include "cc/test/test_texture.h" 22 #include "third_party/khronos/GLES2/gl2.h" 23 #include "ui/gfx/rect.h" 24 25 namespace cc { 26 class TestContextSupport; 27 28 class TestWebGraphicsContext3D { 29 public: 30 static scoped_ptr<TestWebGraphicsContext3D> Create(); 31 32 virtual ~TestWebGraphicsContext3D(); 33 set_context_lost_callback(const base::Closure & callback)34 void set_context_lost_callback(const base::Closure& callback) { 35 context_lost_callback_ = callback; 36 } 37 38 virtual void reshapeWithScaleFactor(int width, 39 int height, 40 float scale_factor); 41 42 virtual bool isContextLost(); 43 discardFramebufferEXT(GLenum target,GLsizei num_attachments,const GLenum * attachments)44 virtual void discardFramebufferEXT(GLenum target, 45 GLsizei num_attachments, 46 const GLenum* attachments) {} 47 activeTexture(GLenum texture)48 virtual void activeTexture(GLenum texture) {} 49 virtual void attachShader(GLuint program, GLuint shader); 50 virtual void bindFramebuffer(GLenum target, GLuint framebuffer); 51 virtual void bindRenderbuffer(GLenum target, GLuint renderbuffer); 52 virtual void bindTexture(GLenum target, GLuint texture_id); 53 54 virtual void texParameteri(GLenum target, GLenum pname, GLint param); 55 virtual void getTexParameteriv(GLenum target, GLenum pname, GLint* value); asyncTexImage2DCHROMIUM(GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,const void * pixels)56 virtual void asyncTexImage2DCHROMIUM(GLenum target, 57 GLint level, 58 GLenum internalformat, 59 GLsizei width, 60 GLsizei height, 61 GLint border, 62 GLenum format, 63 GLenum type, 64 const void* pixels) {} asyncTexSubImage2DCHROMIUM(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,const void * pixels)65 virtual void asyncTexSubImage2DCHROMIUM(GLenum target, 66 GLint level, 67 GLint xoffset, 68 GLint yoffset, 69 GLsizei width, 70 GLsizei height, 71 GLenum format, 72 GLenum type, 73 const void* pixels) {} waitAsyncTexImage2DCHROMIUM(GLenum target)74 virtual void waitAsyncTexImage2DCHROMIUM(GLenum target) {} releaseTexImage2DCHROMIUM(GLenum target,GLint image_id)75 virtual void releaseTexImage2DCHROMIUM(GLenum target, GLint image_id) {} framebufferRenderbuffer(GLenum target,GLenum attachment,GLenum renderbuffertarget,GLuint renderbuffer)76 virtual void framebufferRenderbuffer(GLenum target, 77 GLenum attachment, 78 GLenum renderbuffertarget, 79 GLuint renderbuffer) {} framebufferTexture2D(GLenum target,GLenum attachment,GLenum textarget,GLuint texture,GLint level)80 virtual void framebufferTexture2D(GLenum target, 81 GLenum attachment, 82 GLenum textarget, 83 GLuint texture, 84 GLint level) {} renderbufferStorage(GLenum target,GLenum internalformat,GLsizei width,GLsizei height)85 virtual void renderbufferStorage(GLenum target, 86 GLenum internalformat, 87 GLsizei width, 88 GLsizei height) {} 89 90 virtual GLenum checkFramebufferStatus(GLenum target); 91 clear(GLbitfield mask)92 virtual void clear(GLbitfield mask) {} clearColor(GLclampf red,GLclampf green,GLclampf blue,GLclampf alpha)93 virtual void clearColor(GLclampf red, 94 GLclampf green, 95 GLclampf blue, 96 GLclampf alpha) {} clearStencil(GLint s)97 virtual void clearStencil(GLint s) {} compressedTexImage2D(GLenum target,GLint level,GLenum internal_format,GLsizei width,GLsizei height,GLint border,GLsizei image_size,const void * data)98 virtual void compressedTexImage2D(GLenum target, 99 GLint level, 100 GLenum internal_format, 101 GLsizei width, 102 GLsizei height, 103 GLint border, 104 GLsizei image_size, 105 const void* data) {} 106 virtual GLint getUniformLocation(GLuint program, const GLchar* name); 107 virtual GLsizeiptr getVertexAttribOffset(GLuint index, GLenum pname); 108 109 virtual GLboolean isBuffer(GLuint buffer); 110 virtual GLboolean isEnabled(GLenum cap); 111 virtual GLboolean isFramebuffer(GLuint framebuffer); 112 virtual GLboolean isProgram(GLuint program); 113 virtual GLboolean isRenderbuffer(GLuint renderbuffer); 114 virtual GLboolean isShader(GLuint shader); 115 virtual GLboolean isTexture(GLuint texture); 116 117 virtual void useProgram(GLuint program); 118 viewport(GLint x,GLint y,GLsizei width,GLsizei height)119 virtual void viewport(GLint x, GLint y, GLsizei width, GLsizei height) {} 120 121 virtual void genBuffers(GLsizei count, GLuint* ids); 122 virtual void genFramebuffers(GLsizei count, GLuint* ids); 123 virtual void genRenderbuffers(GLsizei count, GLuint* ids); 124 virtual void genTextures(GLsizei count, GLuint* ids); 125 126 virtual void deleteBuffers(GLsizei count, GLuint* ids); 127 virtual void deleteFramebuffers(GLsizei count, GLuint* ids); 128 virtual void deleteRenderbuffers(GLsizei count, GLuint* ids); 129 virtual void deleteTextures(GLsizei count, GLuint* ids); 130 131 virtual GLuint createBuffer(); 132 virtual GLuint createFramebuffer(); 133 virtual GLuint createRenderbuffer(); 134 virtual GLuint createTexture(); 135 136 virtual void deleteBuffer(GLuint id); 137 virtual void deleteFramebuffer(GLuint id); 138 virtual void deleteRenderbuffer(GLuint id); 139 virtual void deleteTexture(GLuint id); 140 141 virtual GLuint createProgram(); 142 virtual GLuint createShader(GLenum); 143 virtual GLuint createExternalTexture(); 144 145 virtual void deleteProgram(GLuint id); 146 virtual void deleteShader(GLuint id); 147 texStorage2DEXT(GLenum target,GLint levels,GLuint internalformat,GLint width,GLint height)148 virtual void texStorage2DEXT(GLenum target, 149 GLint levels, 150 GLuint internalformat, 151 GLint width, 152 GLint height) {} 153 154 virtual GLuint createQueryEXT(); deleteQueryEXT(GLuint query)155 virtual void deleteQueryEXT(GLuint query) {} beginQueryEXT(GLenum target,GLuint query)156 virtual void beginQueryEXT(GLenum target, GLuint query) {} 157 virtual void endQueryEXT(GLenum target); 158 virtual void getQueryObjectuivEXT(GLuint query, GLenum pname, GLuint* params); 159 scissor(GLint x,GLint y,GLsizei width,GLsizei height)160 virtual void scissor(GLint x, GLint y, GLsizei width, GLsizei height) {} 161 texImage2D(GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,const void * pixels)162 virtual void texImage2D(GLenum target, 163 GLint level, 164 GLenum internalformat, 165 GLsizei width, 166 GLsizei height, 167 GLint border, 168 GLenum format, 169 GLenum type, 170 const void* pixels) {} 171 texSubImage2D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,const void * pixels)172 virtual void texSubImage2D(GLenum target, 173 GLint level, 174 GLint xoffset, 175 GLint yoffset, 176 GLsizei width, 177 GLsizei height, 178 GLenum format, 179 GLenum type, 180 const void* pixels) {} 181 182 virtual void genMailboxCHROMIUM(GLbyte* mailbox); produceTextureCHROMIUM(GLenum target,const GLbyte * mailbox)183 virtual void produceTextureCHROMIUM(GLenum target, 184 const GLbyte* mailbox) { } produceTextureDirectCHROMIUM(GLuint texture,GLenum target,const GLbyte * mailbox)185 virtual void produceTextureDirectCHROMIUM(GLuint texture, 186 GLenum target, 187 const GLbyte* mailbox) {} consumeTextureCHROMIUM(GLenum target,const GLbyte * mailbox)188 virtual void consumeTextureCHROMIUM(GLenum target, 189 const GLbyte* mailbox) { } 190 virtual GLuint createAndConsumeTextureCHROMIUM(GLenum target, 191 const GLbyte* mailbox); 192 193 virtual void loseContextCHROMIUM(GLenum current, GLenum other); 194 bindTexImage2DCHROMIUM(GLenum target,GLint image_id)195 virtual void bindTexImage2DCHROMIUM(GLenum target, GLint image_id) {} 196 drawArrays(GLenum mode,GLint first,GLsizei count)197 virtual void drawArrays(GLenum mode, GLint first, GLsizei count) {} drawElements(GLenum mode,GLsizei count,GLenum type,GLintptr offset)198 virtual void drawElements(GLenum mode, 199 GLsizei count, 200 GLenum type, 201 GLintptr offset) {} disable(GLenum cap)202 virtual void disable(GLenum cap) {} enable(GLenum cap)203 virtual void enable(GLenum cap) {} 204 virtual void finish(); 205 virtual void flush(); shallowFlushCHROMIUM()206 virtual void shallowFlushCHROMIUM() {} 207 getAttachedShaders(GLuint program,GLsizei max_count,GLsizei * count,GLuint * shaders)208 virtual void getAttachedShaders(GLuint program, 209 GLsizei max_count, 210 GLsizei* count, 211 GLuint* shaders) {} 212 virtual GLint getAttribLocation(GLuint program, const GLchar* name); getBooleanv(GLenum pname,GLboolean * value)213 virtual void getBooleanv(GLenum pname, GLboolean* value) {} getBufferParameteriv(GLenum target,GLenum pname,GLint * value)214 virtual void getBufferParameteriv(GLenum target, GLenum pname, GLint* value) { 215 } 216 virtual GLenum getError(); getFloatv(GLenum pname,GLfloat * value)217 virtual void getFloatv(GLenum pname, GLfloat* value) {} getFramebufferAttachmentParameteriv(GLenum target,GLenum attachment,GLenum pname,GLint * value)218 virtual void getFramebufferAttachmentParameteriv(GLenum target, 219 GLenum attachment, 220 GLenum pname, 221 GLint* value) {} 222 223 virtual void getIntegerv(GLenum pname, GLint* value); 224 225 virtual void getProgramiv(GLuint program, GLenum pname, GLint* value); 226 getRenderbufferParameteriv(GLenum target,GLenum pname,GLint * value)227 virtual void getRenderbufferParameteriv(GLenum target, 228 GLenum pname, 229 GLint* value) {} 230 231 virtual void getShaderiv(GLuint shader, GLenum pname, GLint* value); 232 233 virtual void getShaderPrecisionFormat(GLenum shadertype, 234 GLenum precisiontype, 235 GLint* range, 236 GLint* precision); 237 getTexParameterfv(GLenum target,GLenum pname,GLfloat * value)238 virtual void getTexParameterfv(GLenum target, GLenum pname, GLfloat* value) {} getUniformfv(GLuint program,GLint location,GLfloat * value)239 virtual void getUniformfv(GLuint program, GLint location, GLfloat* value) {} getUniformiv(GLuint program,GLint location,GLint * value)240 virtual void getUniformiv(GLuint program, GLint location, GLint* value) {} getVertexAttribfv(GLuint index,GLenum pname,GLfloat * value)241 virtual void getVertexAttribfv(GLuint index, GLenum pname, GLfloat* value) {} getVertexAttribiv(GLuint index,GLenum pname,GLint * value)242 virtual void getVertexAttribiv(GLuint index, GLenum pname, GLint* value) {} 243 244 virtual void bindBuffer(GLenum target, GLuint buffer); 245 virtual void bufferData(GLenum target, 246 GLsizeiptr size, 247 const void* data, 248 GLenum usage); 249 virtual void* mapBufferCHROMIUM(GLenum target, 250 GLenum access); 251 virtual GLboolean unmapBufferCHROMIUM(GLenum target); 252 253 virtual GLuint createImageCHROMIUM(GLsizei width, 254 GLsizei height, 255 GLenum internalformat, 256 GLenum usage); 257 virtual void destroyImageCHROMIUM(GLuint image_id); 258 virtual void getImageParameterivCHROMIUM(GLuint image_id, 259 GLenum pname, 260 GLint* params); 261 virtual void* mapImageCHROMIUM(GLuint image_id); 262 virtual void unmapImageCHROMIUM(GLuint image_id); texImageIOSurface2DCHROMIUM(GLenum target,GLsizei width,GLsizei height,GLuint io_surface_id,GLuint plane)263 virtual void texImageIOSurface2DCHROMIUM(GLenum target, 264 GLsizei width, 265 GLsizei height, 266 GLuint io_surface_id, 267 GLuint plane) {} 268 269 virtual unsigned insertSyncPoint(); 270 virtual void waitSyncPoint(unsigned sync_point); 271 last_waited_sync_point()272 unsigned last_waited_sync_point() const { return last_waited_sync_point_; } 273 test_capabilities()274 const ContextProvider::Capabilities& test_capabilities() const { 275 return test_capabilities_; 276 } 277 set_context_lost(bool context_lost)278 void set_context_lost(bool context_lost) { context_lost_ = context_lost; } set_times_bind_texture_succeeds(int times)279 void set_times_bind_texture_succeeds(int times) { 280 times_bind_texture_succeeds_ = times; 281 } set_times_end_query_succeeds(int times)282 void set_times_end_query_succeeds(int times) { 283 times_end_query_succeeds_ = times; 284 } 285 286 // When set, mapImageCHROMIUM and mapBufferCHROMIUM will return NULL after 287 // this many times. set_times_map_image_chromium_succeeds(int times)288 void set_times_map_image_chromium_succeeds(int times) { 289 times_map_image_chromium_succeeds_ = times; 290 } set_times_map_buffer_chromium_succeeds(int times)291 void set_times_map_buffer_chromium_succeeds(int times) { 292 times_map_buffer_chromium_succeeds_ = times; 293 } 294 295 size_t NumTextures() const; 296 GLuint TextureAt(int i) const; 297 NumUsedTextures()298 size_t NumUsedTextures() const { return used_textures_.size(); } UsedTexture(int texture)299 bool UsedTexture(int texture) const { 300 return ContainsKey(used_textures_, texture); 301 } ResetUsedTextures()302 void ResetUsedTextures() { used_textures_.clear(); } 303 set_have_extension_io_surface(bool have)304 void set_have_extension_io_surface(bool have) { 305 test_capabilities_.gpu.iosurface = have; 306 test_capabilities_.gpu.texture_rectangle = have; 307 } set_have_extension_egl_image(bool have)308 void set_have_extension_egl_image(bool have) { 309 test_capabilities_.gpu.egl_image_external = have; 310 } set_have_post_sub_buffer(bool have)311 void set_have_post_sub_buffer(bool have) { 312 test_capabilities_.gpu.post_sub_buffer = have; 313 } set_have_discard_framebuffer(bool have)314 void set_have_discard_framebuffer(bool have) { 315 test_capabilities_.gpu.discard_framebuffer = have; 316 } set_support_compressed_texture_etc1(bool support)317 void set_support_compressed_texture_etc1(bool support) { 318 test_capabilities_.gpu.texture_format_etc1 = support; 319 } set_support_texture_format_bgra8888(bool support)320 void set_support_texture_format_bgra8888(bool support) { 321 test_capabilities_.gpu.texture_format_bgra8888 = support; 322 } set_support_texture_storage(bool support)323 void set_support_texture_storage(bool support) { 324 test_capabilities_.gpu.texture_storage = support; 325 } set_support_texture_usage(bool support)326 void set_support_texture_usage(bool support) { 327 test_capabilities_.gpu.texture_usage = support; 328 } set_support_sync_query(bool support)329 void set_support_sync_query(bool support) { 330 test_capabilities_.gpu.sync_query = support; 331 } 332 333 // When this context is lost, all contexts in its share group are also lost. add_share_group_context(TestWebGraphicsContext3D * context3d)334 void add_share_group_context(TestWebGraphicsContext3D* context3d) { 335 shared_contexts_.push_back(context3d); 336 } 337 set_max_texture_size(int size)338 void set_max_texture_size(int size) { max_texture_size_ = size; } 339 340 static const GLuint kExternalTextureId; 341 virtual GLuint NextTextureId(); 342 virtual void RetireTextureId(GLuint id); 343 344 virtual GLuint NextBufferId(); 345 virtual void RetireBufferId(GLuint id); 346 347 virtual GLuint NextImageId(); 348 virtual void RetireImageId(GLuint id); 349 350 void SetMaxTransferBufferUsageBytes(size_t max_transfer_buffer_usage_bytes); max_used_transfer_buffer_usage_bytes()351 size_t max_used_transfer_buffer_usage_bytes() const { 352 return max_used_transfer_buffer_usage_bytes_; 353 } 354 set_test_support(TestContextSupport * test_support)355 void set_test_support(TestContextSupport* test_support) { 356 test_support_ = test_support; 357 } 358 width()359 int width() const { return width_; } height()360 int height() const { return height_; } reshape_called()361 bool reshape_called() const { return reshape_called_; } clear_reshape_called()362 void clear_reshape_called() { reshape_called_ = false; } scale_factor()363 float scale_factor() const { return scale_factor_; } 364 365 enum UpdateType { 366 NoUpdate = 0, 367 PrepareTexture, 368 PostSubBuffer 369 }; 370 update_rect()371 gfx::Rect update_rect() const { return update_rect_; } 372 last_update_type()373 UpdateType last_update_type() { return last_update_type_; } 374 375 protected: 376 struct TextureTargets { 377 TextureTargets(); 378 ~TextureTargets(); 379 380 void BindTexture(GLenum target, GLuint id); 381 void UnbindTexture(GLuint id); 382 383 GLuint BoundTexture(GLenum target); 384 385 private: 386 typedef base::hash_map<GLenum, GLuint> TargetTextureMap; 387 TargetTextureMap bound_textures_; 388 }; 389 390 struct Buffer { 391 Buffer(); 392 ~Buffer(); 393 394 GLenum target; 395 scoped_ptr<uint8[]> pixels; 396 size_t size; 397 398 private: 399 DISALLOW_COPY_AND_ASSIGN(Buffer); 400 }; 401 402 struct Image { 403 Image(); 404 ~Image(); 405 406 scoped_ptr<uint8[]> pixels; 407 408 private: 409 DISALLOW_COPY_AND_ASSIGN(Image); 410 }; 411 412 struct Namespace : public base::RefCountedThreadSafe<Namespace> { 413 Namespace(); 414 415 // Protects all fields. 416 base::Lock lock; 417 unsigned next_buffer_id; 418 unsigned next_image_id; 419 unsigned next_texture_id; 420 base::ScopedPtrHashMap<unsigned, Buffer> buffers; 421 base::ScopedPtrHashMap<unsigned, Image> images; 422 OrderedTextureMap textures; 423 424 private: 425 friend class base::RefCountedThreadSafe<Namespace>; 426 ~Namespace(); 427 DISALLOW_COPY_AND_ASSIGN(Namespace); 428 }; 429 430 TestWebGraphicsContext3D(); 431 432 void CreateNamespace(); 433 GLuint BoundTextureId(GLenum target); 434 scoped_refptr<TestTexture> BoundTexture(GLenum target); 435 void CheckTextureIsBound(GLenum target); 436 437 unsigned context_id_; 438 ContextProvider::Capabilities test_capabilities_; 439 int times_bind_texture_succeeds_; 440 int times_end_query_succeeds_; 441 bool context_lost_; 442 int times_map_image_chromium_succeeds_; 443 int times_map_buffer_chromium_succeeds_; 444 int current_used_transfer_buffer_usage_bytes_; 445 int max_used_transfer_buffer_usage_bytes_; 446 base::Closure context_lost_callback_; 447 base::hash_set<unsigned> used_textures_; 448 unsigned next_program_id_; 449 base::hash_set<unsigned> program_set_; 450 unsigned next_shader_id_; 451 base::hash_set<unsigned> shader_set_; 452 std::vector<TestWebGraphicsContext3D*> shared_contexts_; 453 int max_texture_size_; 454 bool reshape_called_; 455 int width_; 456 int height_; 457 float scale_factor_; 458 TestContextSupport* test_support_; 459 gfx::Rect update_rect_; 460 UpdateType last_update_type_; 461 unsigned next_insert_sync_point_; 462 unsigned last_waited_sync_point_; 463 464 unsigned bound_buffer_; 465 TextureTargets texture_targets_; 466 467 scoped_refptr<Namespace> namespace_; 468 static Namespace* shared_namespace_; 469 470 base::WeakPtrFactory<TestWebGraphicsContext3D> weak_ptr_factory_; 471 }; 472 473 } // namespace cc 474 475 #endif // CC_TEST_TEST_WEB_GRAPHICS_CONTEXT_3D_H_ 476