// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CC_TEST_TEST_WEB_GRAPHICS_CONTEXT_3D_H_ #define CC_TEST_TEST_WEB_GRAPHICS_CONTEXT_3D_H_ #include #include "base/callback.h" #include "base/compiler_specific.h" #include "base/containers/hash_tables.h" #include "base/containers/scoped_ptr_hash_map.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/stl_util.h" #include "base/synchronization/lock.h" #include "cc/output/context_provider.h" #include "cc/test/ordered_texture_map.h" #include "cc/test/test_texture.h" #include "third_party/khronos/GLES2/gl2.h" #include "ui/gfx/rect.h" namespace cc { class TestContextSupport; class TestWebGraphicsContext3D { public: static scoped_ptr Create(); virtual ~TestWebGraphicsContext3D(); void set_context_lost_callback(const base::Closure& callback) { context_lost_callback_ = callback; } virtual void reshapeWithScaleFactor(int width, int height, float scale_factor); virtual bool isContextLost(); virtual void discardFramebufferEXT(GLenum target, GLsizei num_attachments, const GLenum* attachments) {} virtual void activeTexture(GLenum texture) {} virtual void attachShader(GLuint program, GLuint shader); virtual void bindFramebuffer(GLenum target, GLuint framebuffer); virtual void bindRenderbuffer(GLenum target, GLuint renderbuffer); virtual void bindTexture(GLenum target, GLuint texture_id); virtual void texParameteri(GLenum target, GLenum pname, GLint param); virtual void getTexParameteriv(GLenum target, GLenum pname, GLint* value); virtual void asyncTexImage2DCHROMIUM(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels) {} virtual void asyncTexSubImage2DCHROMIUM(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels) {} virtual void waitAsyncTexImage2DCHROMIUM(GLenum target) {} virtual void releaseTexImage2DCHROMIUM(GLenum target, GLint image_id) {} virtual GLenum checkFramebufferStatus(GLenum target); virtual void clear(GLbitfield mask) {} virtual void clearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {} virtual void clearStencil(GLint s) {} virtual void compressedTexImage2D(GLenum target, GLint level, GLenum internal_format, GLsizei width, GLsizei height, GLint border, GLsizei image_size, const void* data) {} virtual GLint getUniformLocation(GLuint program, const GLchar* name); virtual GLsizeiptr getVertexAttribOffset(GLuint index, GLenum pname); virtual GLboolean isBuffer(GLuint buffer); virtual GLboolean isEnabled(GLenum cap); virtual GLboolean isFramebuffer(GLuint framebuffer); virtual GLboolean isProgram(GLuint program); virtual GLboolean isRenderbuffer(GLuint renderbuffer); virtual GLboolean isShader(GLuint shader); virtual GLboolean isTexture(GLuint texture); virtual void useProgram(GLuint program); virtual void viewport(GLint x, GLint y, GLsizei width, GLsizei height) {} virtual void genBuffers(GLsizei count, GLuint* ids); virtual void genFramebuffers(GLsizei count, GLuint* ids); virtual void genRenderbuffers(GLsizei count, GLuint* ids); virtual void genTextures(GLsizei count, GLuint* ids); virtual void deleteBuffers(GLsizei count, GLuint* ids); virtual void deleteFramebuffers(GLsizei count, GLuint* ids); virtual void deleteRenderbuffers(GLsizei count, GLuint* ids); virtual void deleteTextures(GLsizei count, GLuint* ids); virtual GLuint createBuffer(); virtual GLuint createFramebuffer(); virtual GLuint createRenderbuffer(); virtual GLuint createTexture(); virtual void deleteBuffer(GLuint id); virtual void deleteFramebuffer(GLuint id); virtual void deleteRenderbuffer(GLuint id); virtual void deleteTexture(GLuint id); virtual GLuint createProgram(); virtual GLuint createShader(GLenum); virtual GLuint createExternalTexture(); virtual void deleteProgram(GLuint id); virtual void deleteShader(GLuint id); virtual void texStorage2DEXT(GLenum target, GLint levels, GLuint internalformat, GLint width, GLint height) {} virtual GLuint createQueryEXT(); virtual void deleteQueryEXT(GLuint query) {} virtual void beginQueryEXT(GLenum target, GLuint query) {} virtual void endQueryEXT(GLenum target); virtual void getQueryObjectuivEXT(GLuint query, GLenum pname, GLuint* params); virtual void scissor(GLint x, GLint y, GLsizei width, GLsizei height) {} virtual void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels) {} virtual void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels) {} virtual void genMailboxCHROMIUM(GLbyte* mailbox); virtual void produceTextureCHROMIUM(GLenum target, const GLbyte* mailbox) { } virtual void produceTextureDirectCHROMIUM(GLuint texture, GLenum target, const GLbyte* mailbox) {} virtual void consumeTextureCHROMIUM(GLenum target, const GLbyte* mailbox) { } virtual GLuint createAndConsumeTextureCHROMIUM(GLenum target, const GLbyte* mailbox); virtual void loseContextCHROMIUM(GLenum current, GLenum other); virtual void bindTexImage2DCHROMIUM(GLenum target, GLint image_id) {} virtual void drawArrays(GLenum mode, GLint first, GLsizei count) {} virtual void drawElements(GLenum mode, GLsizei count, GLenum type, GLintptr offset) {} virtual void disable(GLenum cap) {} virtual void enable(GLenum cap) {} virtual void finish(); virtual void flush(); virtual void shallowFlushCHROMIUM() {} virtual void getAttachedShaders(GLuint program, GLsizei max_count, GLsizei* count, GLuint* shaders) {} virtual GLint getAttribLocation(GLuint program, const GLchar* name); virtual void getBooleanv(GLenum pname, GLboolean* value) {} virtual void getBufferParameteriv(GLenum target, GLenum pname, GLint* value) { } virtual GLenum getError(); virtual void getFloatv(GLenum pname, GLfloat* value) {} virtual void getFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* value) {} virtual void getIntegerv(GLenum pname, GLint* value); virtual void getProgramiv(GLuint program, GLenum pname, GLint* value); virtual void getRenderbufferParameteriv(GLenum target, GLenum pname, GLint* value) {} virtual void getShaderiv(GLuint shader, GLenum pname, GLint* value); virtual void getShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision); virtual void getTexParameterfv(GLenum target, GLenum pname, GLfloat* value) {} virtual void getUniformfv(GLuint program, GLint location, GLfloat* value) {} virtual void getUniformiv(GLuint program, GLint location, GLint* value) {} virtual void getVertexAttribfv(GLuint index, GLenum pname, GLfloat* value) {} virtual void getVertexAttribiv(GLuint index, GLenum pname, GLint* value) {} virtual void bindBuffer(GLenum target, GLuint buffer); virtual void bufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage); virtual void* mapBufferCHROMIUM(GLenum target, GLenum access); virtual GLboolean unmapBufferCHROMIUM(GLenum target); virtual GLuint createImageCHROMIUM(GLsizei width, GLsizei height, GLenum internalformat, GLenum usage); virtual void destroyImageCHROMIUM(GLuint image_id); virtual void getImageParameterivCHROMIUM(GLuint image_id, GLenum pname, GLint* params); virtual void* mapImageCHROMIUM(GLuint image_id); virtual void unmapImageCHROMIUM(GLuint image_id); virtual void texImageIOSurface2DCHROMIUM(GLenum target, GLsizei width, GLsizei height, GLuint io_surface_id, GLuint plane) {} virtual unsigned insertSyncPoint(); virtual void waitSyncPoint(unsigned sync_point); unsigned last_waited_sync_point() const { return last_waited_sync_point_; } const ContextProvider::Capabilities& test_capabilities() const { return test_capabilities_; } void set_context_lost(bool context_lost) { context_lost_ = context_lost; } void set_times_bind_texture_succeeds(int times) { times_bind_texture_succeeds_ = times; } void set_times_end_query_succeeds(int times) { times_end_query_succeeds_ = times; } // When set, mapImageCHROMIUM and mapBufferCHROMIUM will return NULL after // this many times. void set_times_map_image_chromium_succeeds(int times) { times_map_image_chromium_succeeds_ = times; } void set_times_map_buffer_chromium_succeeds(int times) { times_map_buffer_chromium_succeeds_ = times; } size_t NumTextures() const; GLuint TextureAt(int i) const; size_t NumUsedTextures() const { return used_textures_.size(); } bool UsedTexture(int texture) const { return ContainsKey(used_textures_, texture); } void ResetUsedTextures() { used_textures_.clear(); } void set_have_extension_io_surface(bool have) { test_capabilities_.gpu.iosurface = have; test_capabilities_.gpu.texture_rectangle = have; } void set_have_extension_egl_image(bool have) { test_capabilities_.gpu.egl_image_external = have; } void set_have_post_sub_buffer(bool have) { test_capabilities_.gpu.post_sub_buffer = have; } void set_have_discard_framebuffer(bool have) { test_capabilities_.gpu.discard_framebuffer = have; } void set_support_compressed_texture_etc1(bool support) { test_capabilities_.gpu.texture_format_etc1 = support; } void set_support_texture_format_bgra8888(bool support) { test_capabilities_.gpu.texture_format_bgra8888 = support; } void set_support_texture_storage(bool support) { test_capabilities_.gpu.texture_storage = support; } void set_support_texture_usage(bool support) { test_capabilities_.gpu.texture_usage = support; } void set_support_sync_query(bool support) { test_capabilities_.gpu.sync_query = support; } // When this context is lost, all contexts in its share group are also lost. void add_share_group_context(TestWebGraphicsContext3D* context3d) { shared_contexts_.push_back(context3d); } void set_max_texture_size(int size) { max_texture_size_ = size; } static const GLuint kExternalTextureId; virtual GLuint NextTextureId(); virtual void RetireTextureId(GLuint id); virtual GLuint NextBufferId(); virtual void RetireBufferId(GLuint id); virtual GLuint NextImageId(); virtual void RetireImageId(GLuint id); void SetMaxTransferBufferUsageBytes(size_t max_transfer_buffer_usage_bytes); size_t max_used_transfer_buffer_usage_bytes() const { return max_used_transfer_buffer_usage_bytes_; } void set_test_support(TestContextSupport* test_support) { test_support_ = test_support; } int width() const { return width_; } int height() const { return height_; } bool reshape_called() const { return reshape_called_; } void clear_reshape_called() { reshape_called_ = false; } float scale_factor() const { return scale_factor_; } enum UpdateType { NoUpdate = 0, PrepareTexture, PostSubBuffer }; gfx::Rect update_rect() const { return update_rect_; } UpdateType last_update_type() { return last_update_type_; } protected: struct TextureTargets { TextureTargets(); ~TextureTargets(); void BindTexture(GLenum target, GLuint id); void UnbindTexture(GLuint id); GLuint BoundTexture(GLenum target); private: typedef base::hash_map TargetTextureMap; TargetTextureMap bound_textures_; }; struct Buffer { Buffer(); ~Buffer(); GLenum target; scoped_ptr pixels; size_t size; private: DISALLOW_COPY_AND_ASSIGN(Buffer); }; struct Image { Image(); ~Image(); scoped_ptr pixels; private: DISALLOW_COPY_AND_ASSIGN(Image); }; struct Namespace : public base::RefCountedThreadSafe { Namespace(); // Protects all fields. base::Lock lock; unsigned next_buffer_id; unsigned next_image_id; unsigned next_texture_id; base::ScopedPtrHashMap buffers; base::ScopedPtrHashMap images; OrderedTextureMap textures; private: friend class base::RefCountedThreadSafe; ~Namespace(); DISALLOW_COPY_AND_ASSIGN(Namespace); }; TestWebGraphicsContext3D(); void CreateNamespace(); GLuint BoundTextureId(GLenum target); scoped_refptr BoundTexture(GLenum target); void CheckTextureIsBound(GLenum target); unsigned context_id_; ContextProvider::Capabilities test_capabilities_; int times_bind_texture_succeeds_; int times_end_query_succeeds_; bool context_lost_; int times_map_image_chromium_succeeds_; int times_map_buffer_chromium_succeeds_; int current_used_transfer_buffer_usage_bytes_; int max_used_transfer_buffer_usage_bytes_; base::Closure context_lost_callback_; base::hash_set used_textures_; unsigned next_program_id_; base::hash_set program_set_; unsigned next_shader_id_; base::hash_set shader_set_; std::vector shared_contexts_; int max_texture_size_; bool reshape_called_; int width_; int height_; float scale_factor_; TestContextSupport* test_support_; gfx::Rect update_rect_; UpdateType last_update_type_; unsigned next_insert_sync_point_; unsigned last_waited_sync_point_; unsigned bound_buffer_; TextureTargets texture_targets_; scoped_refptr namespace_; static Namespace* shared_namespace_; base::WeakPtrFactory weak_ptr_factory_; }; } // namespace cc #endif // CC_TEST_TEST_WEB_GRAPHICS_CONTEXT_3D_H_