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