Chromium Code Reviews| Index: webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc |
| diff --git a/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc b/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc |
| index 62439d8ed2bf1d6070a05ba463d106f151ffb019..7cf7cf4f89816244f7cb3c46c33ec4d9872ffef3 100644 |
| --- a/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc |
| +++ b/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc |
| @@ -2,574 +2,918 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| +#if defined(ENABLE_GPU) |
| + |
| #include "webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h" |
| -#include <string.h> |
| +#include <GLES2/gl2.h> |
| +#ifndef GL_GLEXT_PROTOTYPES |
| +#define GL_GLEXT_PROTOTYPES 1 |
| +#endif |
| +#include <GLES2/gl2ext.h> |
| #include <algorithm> |
| -#include <string> |
| +#include "base/string_tokenizer.h" |
| +#include "base/command_line.h" |
| +#include "base/lazy_instance.h" |
| #include "base/logging.h" |
| +#include "base/memory/singleton.h" |
| +#include "base/metrics/histogram.h" |
| +#include "content/common/content_switches.h" |
| +#include "gpu/command_buffer/client/gles2_lib.h" |
| +#include "gpu/command_buffer/client/gles2_implementation.h" |
| +#include "gpu/command_buffer/common/constants.h" |
| +#include "gpu/command_buffer/service/gpu_scheduler.h" |
| +#include "gpu/command_buffer/service/command_buffer_service.h" |
| +#include "gpu/GLES2/gles2_command_buffer.h" |
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
| -#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" |
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
| -#include "ui/gfx/gl/gl_bindings.h" |
| -#include "ui/gfx/gl/gl_bindings_skia_in_process.h" |
| -#include "ui/gfx/gl/gl_context.h" |
| -#include "ui/gfx/gl/gl_implementation.h" |
| -#include "ui/gfx/gl/gl_surface.h" |
| +#include "webkit/glue/gl_bindings_skia_cmd_buffer.h" |
| + |
| +using gpu::Buffer; |
| +using gpu::CommandBuffer; |
| +using gpu::CommandBufferService; |
| +using gpu::gles2::GLES2CmdHelper; |
| +using gpu::gles2::GLES2Implementation; |
| +using gpu::GpuScheduler; |
| namespace webkit { |
| namespace gpu { |
| -enum { |
| - MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB, |
| - MAX_VARYING_VECTORS = 0x8DFC, |
| - MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD |
| -}; |
| +class GLInProcessContext : public base::SupportsWeakPtr<GLInProcessContext> { |
| + public: |
| + // These are the same error codes as used by EGL. |
| + enum Error { |
| + SUCCESS = 0x3000, |
| + NOT_INITIALIZED = 0x3001, |
| + BAD_ATTRIBUTE = 0x3004, |
| + BAD_GLContext = 0x3006, |
| + CONTEXT_LOST = 0x300E |
| + }; |
| + |
| + // GLInProcessContext configuration attributes. These are the same as used by |
| + // EGL. Attributes are matched using a closest fit algorithm. |
| + enum Attribute { |
| + ALPHA_SIZE = 0x3021, |
| + BLUE_SIZE = 0x3022, |
| + GREEN_SIZE = 0x3023, |
| + RED_SIZE = 0x3024, |
| + DEPTH_SIZE = 0x3025, |
| + STENCIL_SIZE = 0x3026, |
| + SAMPLES = 0x3031, |
| + SAMPLE_BUFFERS = 0x3032, |
| + NONE = 0x3038 // Attrib list = terminator |
| + }; |
| + |
| + // Initialize the library. This must have completed before any other |
| + // functions are invoked. |
| + static bool Initialize(); |
| + |
| + // Terminate the library. This must be called after any other functions |
| + // have completed. |
| + static bool Terminate(); |
| + |
| + ~GLInProcessContext(); |
| + |
| + // Create a GLInProcessContext that renders directly to a view. The view and |
| + // the associated window must not be destroyed until the returned |
| + // GLInProcessContext has been destroyed, otherwise the GPU process might |
| + // attempt to render to an invalid window handle. |
| + // |
| + // NOTE: on Mac OS X, this entry point is only used to set up the |
| + // accelerated compositor's output. On this platform, we actually pass |
| + // a gfx::PluginWindowHandle in place of the gfx::NativeViewId, |
| + // because the facility to allocate a fake PluginWindowHandle is |
| + // already in place. We could add more entry points and messages to |
| + // allocate both fake PluginWindowHandles and NativeViewIds and map |
| + // from fake NativeViewIds to PluginWindowHandles, but this seems like |
| + // unnecessary complexity at the moment. |
| + // |
| + static GLInProcessContext* CreateViewContext( |
| + gfx::PluginWindowHandle render_surface, |
| + const char* allowed_extensions, |
| + const int32* attrib_list, |
| + const GURL& active_arl); |
| -struct WebGraphicsContext3DInProcessCommandBufferImpl::ShaderSourceEntry { |
| - explicit ShaderSourceEntry(WGC3Denum shader_type) |
| - : type(shader_type), |
| - is_valid(false) { |
| - } |
| +#if defined(OS_MACOSX) |
| + // On Mac OS X only, view GLInProcessContexts actually behave like offscreen |
| + // GLInProcessContexts, and require an explicit resize operation which is |
| + // slightly different from that of offscreen GLInProcessContexts. |
| + void ResizeOnscreen(const gfx::Size& size); |
| +#endif |
| - WGC3Denum type; |
| - scoped_array<char> source; |
| - scoped_array<char> log; |
| - scoped_array<char> translated_source; |
| - bool is_valid; |
| + // Create a GLInProcessContext that renders to an offscreen frame buffer. If |
| + // parent is not NULL, that GLInProcessContext can access a copy of the |
| + // created GLInProcessContext's frame buffer that is updated every time |
| + // SwapBuffers is called. It is not as general as shared GLInProcessContexts |
| + // in other implementations of OpenGL. If parent is not NULL, it must be used |
| + // on the same thread as the parent. A child GLInProcessContext may not |
| + // outlive its parent. attrib_list must be NULL or a NONE-terminated list of |
| + // attribute/value pairs. |
| + static GLInProcessContext* CreateOffscreenContext( |
| + GLInProcessContext* parent, |
| + const gfx::Size& size, |
| + const char* allowed_extensions, |
| + const int32* attrib_list, |
| + const GURL& active_url); |
| + |
| + // Resize an offscreen frame buffer. The resize occurs on the next call to |
| + // SwapBuffers. This is to avoid waiting until all pending GL calls have been |
| + // executed by the GPU process. Everything rendered up to the call to |
| + // SwapBuffers will be lost. A lost GLInProcessContext will be reported if the |
| + // resize fails. |
| + void ResizeOffscreen(const gfx::Size& size); |
| + |
| + // For an offscreen frame buffer GLInProcessContext, return the texture ID |
| + // with respect to the parent GLInProcessContext. Returns zero if |
| + // GLInProcessContext does not have a parent. |
| + uint32 GetParentTextureId(); |
| + |
| + // Create a new texture in the parent's GLInProcessContext. Returns zero if |
| + // GLInProcessContext does not have a parent. |
| + uint32 CreateParentTexture(const gfx::Size& size); |
| + |
| + // Deletes a texture in the parent's GLInProcessContext. |
| + void DeleteParentTexture(uint32 texture); |
| + |
| + // Provides a callback that will be invoked when SwapBuffers has completed |
| + // service side. |
| + void SetSwapBuffersCallback(Callback0::Type* callback); |
| + |
| + void SetContextLostCallback(Callback0::Type* callback); |
| + |
| + // Set the current GLInProcessContext for the calling thread. |
| + static bool MakeCurrent(GLInProcessContext* context); |
| + |
| + // For a view GLInProcessContext, display everything that has been rendered |
| + // since the last call. For an offscreen GLInProcessContext, resolve |
| + // everything that has been rendered since the last call to a copy that can be |
| + // accessed by the parent GLInProcessContext. |
| + bool SwapBuffers(); |
| + |
| + // TODO(gman): Remove this |
| + void DisableShaderTranslation(); |
| + |
| + // Allows direct access to the GLES2 implementation so a GLInProcessContext |
| + // can be used without making it current. |
| + GLES2Implementation* GetImplementation(); |
| + |
| + // Return the current error. |
| + Error GetError(); |
| + |
| + // Return true if GPU process reported GLInProcessContext lost or there was a |
| + // problem communicating with the GPU process. |
| + bool IsCommandBufferContextLost(); |
| + |
| + CommandBufferService* GetCommandBufferService(); |
| + |
| + // Create a latch for synchronization between contexts using glSetLatch and |
| + // glWaitLatch. |
| + // CreateLatch will only fail if there is a generally unrecoverable |
| + // error, in which case 0 is returned. Returns latch_id on success. |
| + bool CreateLatch(uint32* ret_latch); |
| + |
| + // Destroy a latch. |
| + bool DestroyLatch(uint32 latch); |
| + |
| + // All child contexts get a latch pair automatically. These latches are used |
| + // for synchronization with parent context. If *this* context does not have a |
| + // parent context, these methods will return false. |
| + bool GetParentToChildLatch(uint32* parent_to_child_latch); |
| + bool GetChildToParentLatch(uint32* child_to_parent_latch); |
| + |
| + private: |
| + GLInProcessContext(GLInProcessContext* parent); |
| + |
| + bool Initialize(bool onscreen, |
| + gfx::PluginWindowHandle render_surface, |
| + const gfx::Size& size, |
| + const char* allowed_extensions, |
| + const int32* attrib_list, |
| + const GURL& active_url); |
| + void Destroy(); |
| + |
| + void OnSwapBuffers(); |
| + void OnContextLost(); |
| + |
| + base::WeakPtr<GLInProcessContext> parent_; |
| + scoped_ptr<Callback0::Type> swap_buffers_callback_; |
| + scoped_ptr<Callback0::Type> context_lost_callback_; |
| + uint32 parent_texture_id_; |
| + uint32 child_to_parent_latch_; |
| + uint32 parent_to_child_latch_; |
| + int32 latch_transfer_buffer_id_; |
| + scoped_ptr<CommandBufferService> command_buffer_; |
| + GpuScheduler* gpu_scheduler_; |
| + GLES2CmdHelper* gles2_helper_; |
| + int32 transfer_buffer_id_; |
| + GLES2Implementation* gles2_implementation_; |
| + gfx::Size size_; |
| + Error last_error_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(GLInProcessContext); |
| }; |
| -WebGraphicsContext3DInProcessCommandBufferImpl::WebGraphicsContext3DInProcessCommandBufferImpl() |
| - : initialized_(false), |
| - render_directly_to_web_view_(false), |
| - is_gles2_(false), |
| - have_ext_framebuffer_object_(false), |
| - have_ext_framebuffer_multisample_(false), |
| - have_angle_framebuffer_multisample_(false), |
| - texture_(0), |
| - fbo_(0), |
| - depth_stencil_buffer_(0), |
| - cached_width_(0), |
| - cached_height_(0), |
| - multisample_fbo_(0), |
| - multisample_depth_stencil_buffer_(0), |
| - multisample_color_buffer_(0), |
| - bound_fbo_(0), |
| - bound_texture_(0), |
| - copy_texture_to_parent_texture_fbo_(0), |
| -#ifdef FLIP_FRAMEBUFFER_VERTICALLY |
| - scanline_(0), |
| -#endif |
| - fragment_compiler_(0), |
| - vertex_compiler_(0) { |
| -} |
| +namespace { |
| -WebGraphicsContext3DInProcessCommandBufferImpl::~WebGraphicsContext3DInProcessCommandBufferImpl() { |
| - if (!initialized_) |
| - return; |
| +const int32 kCommandBufferSize = 1024 * 1024; |
| +// TODO(kbr): make the transfer buffer size configurable via context |
| +// creation attributes. |
| +const int32 kTransferBufferSize = 1024 * 1024; |
| - makeContextCurrent(); |
| +const uint32 kMaxLatchesPerRenderer = 2048; |
| +const uint32 kInvalidLatchId = 0xffffffffu; |
| - if (attributes_.antialias) { |
| - glDeleteRenderbuffersEXT(1, &multisample_color_buffer_); |
| - if (attributes_.depth || attributes_.stencil) |
| - glDeleteRenderbuffersEXT(1, &multisample_depth_stencil_buffer_); |
| - glDeleteFramebuffersEXT(1, &multisample_fbo_); |
| - } else { |
| - if (attributes_.depth || attributes_.stencil) |
| - glDeleteRenderbuffersEXT(1, &depth_stencil_buffer_); |
| +// Singleton used to initialize and terminate the gles2 library. |
| +class GLES2Initializer { |
| + public: |
| + GLES2Initializer() { |
| + gles2::Initialize(); |
| } |
| - glDeleteTextures(1, &texture_); |
| - glDeleteFramebuffersEXT(1, ©_texture_to_parent_texture_fbo_); |
| -#ifdef FLIP_FRAMEBUFFER_VERTICALLY |
| - if (scanline_) |
| - delete[] scanline_; |
| -#endif |
| - glDeleteFramebuffersEXT(1, &fbo_); |
| - |
| - gl_context_->Destroy(); |
| - for (ShaderSourceMap::iterator ii = shader_source_map_.begin(); |
| - ii != shader_source_map_.end(); ++ii) { |
| - if (ii->second) |
| - delete ii->second; |
| + ~GLES2Initializer() { |
| + gles2::Terminate(); |
| } |
| - AngleDestroyCompilers(); |
| -} |
| -bool WebGraphicsContext3DInProcessCommandBufferImpl::initialize( |
| - WebGraphicsContext3D::Attributes attributes, |
| - WebView* webView, |
| - bool render_directly_to_web_view) { |
| - if (!gfx::GLSurface::InitializeOneOff()) |
| - return false; |
| - gfx::BindSkiaToInProcessGL(); |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(GLES2Initializer); |
| +}; |
| - render_directly_to_web_view_ = render_directly_to_web_view; |
| - gfx::GLContext* share_context = 0; |
| +// Shared memory allocator for latches. Creates a block of shared memory for |
|
jamesr
2011/06/01 02:07:02
this isn't really shared memory in this implementa
greggman
2011/06/01 21:55:39
Done.
|
| +// each renderer process. |
| +class LatchAllocator { |
| + public: |
| + static LatchAllocator* GetInstance(); |
| + static uint32 size() { return kMaxLatchesPerRenderer*sizeof(uint32); } |
| + static const uint32_t kFreeLatch = 0xffffffffu; |
| - if (!render_directly_to_web_view) { |
| - // Pick up the compositor's context to share resources with. |
| - WebGraphicsContext3D* view_context = webView->graphicsContext3D(); |
| - if (view_context) { |
| - WebGraphicsContext3DInProcessCommandBufferImpl* contextImpl = |
| - static_cast<WebGraphicsContext3DInProcessCommandBufferImpl*>(view_context); |
| - share_context = contextImpl->gl_context_.get(); |
| - } else { |
| - // The compositor's context didn't get created |
| - // successfully, so conceptually there is no way we can |
| - // render successfully to the WebView. |
| - render_directly_to_web_view_ = false; |
| - } |
| - } |
| + LatchAllocator(); |
| + ~LatchAllocator(); |
| - is_gles2_ = gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2; |
| + bool AllocateLatch(uint32* latch_id); |
| + bool FreeLatch(uint32 latch_id); |
| - // This implementation always renders offscreen regardless of |
| - // whether render_directly_to_web_view is true. Both DumpRenderTree |
| - // and test_shell paint first to an intermediate offscreen buffer |
| - // and from there to the window, and WebViewImpl::paint already |
| - // correctly handles the case where the compositor is active but |
| - // the output needs to go to a WebCanvas. |
| - gl_surface_.reset(gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(1, 1))); |
| + private: |
| + friend struct DefaultSingletonTraits<LatchAllocator>; |
| - if (!gl_surface_.get()) { |
| - if (!is_gles2_) |
| - return false; |
| + // Because this is in process this can just be normal memory. |
| + scoped_array<uint32> memory_; |
| - // Embedded systems have smaller limit on number of GL contexts. Sometimes |
| - // failure of GL context creation is because of existing GL contexts |
| - // referenced by JavaScript garbages. Collect garbage and try again. |
| - // TODO: Besides this solution, kbr@chromium.org suggested: upon receiving |
| - // a page unload event, iterate down any live WebGraphicsContext3D instances |
| - // and force them to drop their contexts, sending a context lost event if |
| - // necessary. |
| - webView->mainFrame()->collectGarbage(); |
| - |
| - gl_surface_.reset(gfx::GLSurface::CreateOffscreenGLSurface( |
| - gfx::Size(1, 1))); |
| - if (!gl_surface_.get()) |
| - return false; |
| - } |
| + // Pointer to mapped shared memory. |
|
jamesr
2011/06/01 02:07:02
this is confusing - can't we just use memory_ (and
greggman
2011/06/01 21:55:39
Done.
|
| + volatile uint32* latches_; |
| - gl_context_.reset(gfx::GLContext::CreateGLContext(share_context, |
| - gl_surface_.get())); |
| - if (!gl_context_.get()) { |
| - if (!is_gles2_) |
| - return false; |
| + DISALLOW_COPY_AND_ASSIGN(LatchAllocator); |
| +}; |
| - // Embedded systems have smaller limit on number of GL contexts. Sometimes |
| - // failure of GL context creation is because of existing GL contexts |
| - // referenced by JavaScript garbages. Collect garbage and try again. |
| - // TODO: Besides this solution, kbr@chromium.org suggested: upon receiving |
| - // a page unload event, iterate down any live WebGraphicsContext3D instances |
| - // and force them to drop their contexts, sending a context lost event if |
| - // necessary. |
| - webView->mainFrame()->collectGarbage(); |
| - |
| - gl_context_.reset(gfx::GLContext::CreateGLContext(share_context, |
| - gl_surface_.get())); |
| - if (!gl_context_.get()) |
| - return false; |
| - } |
| +//////////////////////////////////////////////////////////////////////////////// |
| +/// LatchAllocator implementation |
| - attributes_ = attributes; |
| - |
| - // FIXME: for the moment we disable multisampling for the compositor. |
| - // It actually works in this implementation, but there are a few |
| - // considerations. First, we likely want to reduce the fuzziness in |
| - // these tests as much as possible because we want to run pixel tests. |
| - // Second, Mesa's multisampling doesn't seem to antialias straight |
| - // edges in some CSS 3D samples. Third, we don't have multisampling |
| - // support for the compositor in the normal case at the time of this |
| - // writing. |
| - if (render_directly_to_web_view) |
| - attributes_.antialias = false; |
| - |
| - if (!gl_context_->MakeCurrent(gl_surface_.get())) { |
| - gl_context_.reset(); |
| - return false; |
| - } |
| +LatchAllocator* LatchAllocator::GetInstance() { |
| + return Singleton<LatchAllocator>::get(); |
| +} |
| - const char* extensions = |
| - reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); |
| - DCHECK(extensions); |
| - have_ext_framebuffer_object_ = |
| - strstr(extensions, "GL_EXT_framebuffer_object") != NULL; |
| - have_ext_framebuffer_multisample_ = |
| - strstr(extensions, "GL_EXT_framebuffer_multisample") != NULL; |
| - have_angle_framebuffer_multisample_ = |
| - strstr(extensions, "GL_ANGLE_framebuffer_multisample") != NULL; |
| - |
| - ValidateAttributes(); |
| - |
| - if (!is_gles2_) { |
| - glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); |
| - glEnable(GL_POINT_SPRITE); |
| +LatchAllocator::LatchAllocator() { |
| + memory_.reset(new uint32[size()]); |
| + latches_ = memory_.get(); |
| + // Mark all latches as unallocated. |
| + for (uint32 i = 0; i < kMaxLatchesPerRenderer; ++i) |
| + latches_[i] = kFreeLatch; |
| +} |
| + |
| +LatchAllocator::~LatchAllocator() { |
| +} |
| + |
| +bool LatchAllocator::AllocateLatch(uint32* latch_id) { |
| + for (uint32 i = 0; i < kMaxLatchesPerRenderer; ++i) { |
| + if (latches_[i] == kFreeLatch) { |
| + // mark latch as taken and blocked. |
| + // 0 means waiter will block, 1 means waiter will pass. |
| + latches_[i] = 0; |
| + *latch_id = i; |
| + return true; |
| + } |
| } |
| + return false; |
| +} |
| - if (!AngleCreateCompilers()) { |
| - AngleDestroyCompilers(); |
| - return false; |
| +bool LatchAllocator::FreeLatch(uint32 latch_id) { |
| + if (latch_id < kMaxLatchesPerRenderer && latches_[latch_id] != kFreeLatch) { |
| + latches_[latch_id] = kFreeLatch; |
| + return true; |
| } |
| + return false; |
| +} |
| - glGenFramebuffersEXT(1, ©_texture_to_parent_texture_fbo_); |
| +//////////////////////////////////////////////////////////////////////////////// |
| - initialized_ = true; |
| - return true; |
| +static base::LazyInstance<GLES2Initializer> g_gles2_initializer( |
| + base::LINKER_INITIALIZED); |
| + |
| +} // namespace anonymous |
| + |
| +GLInProcessContext::~GLInProcessContext() { |
| + Destroy(); |
| } |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::ValidateAttributes() { |
| - const char* extensions = |
| - reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); |
| +GLInProcessContext* GLInProcessContext::CreateViewContext( |
| + gfx::PluginWindowHandle render_surface, |
| + const char* allowed_extensions, |
| + const int32* attrib_list, |
| + const GURL& active_url) { |
| +#if defined(ENABLE_GPU) |
| + scoped_ptr<GLInProcessContext> context(new GLInProcessContext(NULL)); |
| + if (!context->Initialize( |
| + true, |
| + render_surface, |
| + gfx::Size(), |
| + allowed_extensions, |
| + attrib_list, |
| + active_url)) |
| + return NULL; |
| + |
| + return context.release(); |
| +#else |
| + return NULL; |
| +#endif |
| +} |
| - if (attributes_.stencil) { |
| - if (strstr(extensions, "GL_OES_packed_depth_stencil") || |
| - strstr(extensions, "GL_EXT_packed_depth_stencil")) { |
| - if (!attributes_.depth) { |
| - attributes_.depth = true; |
| - } |
| - } else { |
| - attributes_.stencil = false; |
| - } |
| - } |
| - if (attributes_.antialias) { |
| - bool isValidVendor = true; |
| #if defined(OS_MACOSX) |
| - // Currently in Mac we only turn on antialias if vendor is NVIDIA. |
| - const char* vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); |
| - if (!strstr(vendor, "NVIDIA")) |
| - isValidVendor = false; |
| +void GLInProcessContext::ResizeOnscreen(const gfx::Size& size) { |
| + DCHECK(size.width() > 0 && size.height() > 0); |
| + size_ = size; |
| +} |
| #endif |
| - if (!(isValidVendor && |
| - (have_ext_framebuffer_multisample_ || |
| - (have_angle_framebuffer_multisample_ && |
| - strstr(extensions, "GL_OES_rgb8_rgba8"))))) |
| - attributes_.antialias = false; |
| - |
| - // Don't antialias when using Mesa to ensure more reliable testing and |
| - // because it doesn't appear to multisample straight lines correctly. |
| - const char* renderer = |
| - reinterpret_cast<const char*>(glGetString(GL_RENDERER)); |
| - if (!strncmp(renderer, "Mesa", 4)) { |
| - attributes_.antialias = false; |
| - } |
| + |
| +GLInProcessContext* GLInProcessContext::CreateOffscreenContext( |
| + GLInProcessContext* parent, |
| + const gfx::Size& size, |
| + const char* allowed_extensions, |
| + const int32* attrib_list, |
| + const GURL& active_url) { |
| +#if defined(ENABLE_GPU) |
| + scoped_ptr<GLInProcessContext> context(new GLInProcessContext(parent)); |
| + if (!context->Initialize( |
| + false, |
| + gfx::kNullPluginWindow, |
| + size, |
| + allowed_extensions, |
| + attrib_list, |
| + active_url)) |
| + return NULL; |
| + |
| + return context.release(); |
| +#else |
| + return NULL; |
| +#endif |
| +} |
| + |
| +void GLInProcessContext::ResizeOffscreen(const gfx::Size& size) { |
| + DCHECK(size.width() > 0 && size.height() > 0); |
| + if (size_ != size) { |
| + gpu_scheduler_->ResizeOffscreenFrameBuffer(size); |
| + // TODO(gman): See if the next line is needed. |
| + gles2_implementation_->ResizeCHROMIUM(size.width(), size.height()); |
| + size_ = size; |
| } |
| } |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::ResolveMultisampledFramebuffer( |
| - WGC3Dint x, WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height) { |
| - if (attributes_.antialias) { |
| - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, multisample_fbo_); |
| - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fbo_); |
| - if (have_ext_framebuffer_multisample_) { |
| - glBlitFramebufferEXT(x, y, |
| - x + width, y + height, |
| - x, y, |
| - x + width, y + height, |
| - GL_COLOR_BUFFER_BIT, GL_NEAREST); |
| - } else { |
| - DCHECK(have_angle_framebuffer_multisample_); |
| - glBlitFramebufferANGLE(x, y, |
| - x + width, y + height, |
| - x, y, |
| - x + width, y + height, |
| - GL_COLOR_BUFFER_BIT, GL_NEAREST); |
| - } |
| - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); |
| +uint32 GLInProcessContext::GetParentTextureId() { |
| + return parent_texture_id_; |
| +} |
| + |
| +uint32 GLInProcessContext::CreateParentTexture(const gfx::Size& size) { |
| + // Allocate a texture ID with respect to the parent. |
| + if (parent_.get()) { |
| + if (!MakeCurrent(parent_.get())) |
| + return 0; |
| + uint32 texture_id = parent_->gles2_implementation_->MakeTextureId(); |
| + parent_->gles2_implementation_->BindTexture(GL_TEXTURE_2D, texture_id); |
| + parent_->gles2_implementation_->TexParameteri( |
| + GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| + parent_->gles2_implementation_->TexParameteri( |
| + GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| + parent_->gles2_implementation_->TexParameteri( |
| + GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| + parent_->gles2_implementation_->TexParameteri( |
| + GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| + |
| + parent_->gles2_implementation_->TexImage2D(GL_TEXTURE_2D, |
| + 0, // mip level |
| + GL_RGBA, |
| + size.width(), |
| + size.height(), |
| + 0, // border |
| + GL_RGBA, |
| + GL_UNSIGNED_BYTE, |
| + NULL); |
| + // Make sure that the parent texture's storage is allocated before we let |
| + // the caller attempt to use it. |
| + int32 token = parent_->gles2_helper_->InsertToken(); |
| + parent_->gles2_helper_->WaitForToken(token); |
| + return texture_id; |
| } |
| + return 0; |
| } |
| -bool WebGraphicsContext3DInProcessCommandBufferImpl::makeContextCurrent() { |
| - return gl_context_->MakeCurrent(gl_surface_.get()); |
| +void GLInProcessContext::DeleteParentTexture(uint32 texture) { |
| + if (parent_.get()) { |
| + if (!MakeCurrent(parent_.get())) |
| + return; |
| + parent_->gles2_implementation_->DeleteTextures(1, &texture); |
| + } |
| } |
| -int WebGraphicsContext3DInProcessCommandBufferImpl::width() { |
| - return cached_width_; |
| +void GLInProcessContext::SetSwapBuffersCallback(Callback0::Type* callback) { |
| + swap_buffers_callback_.reset(callback); |
| } |
| -int WebGraphicsContext3DInProcessCommandBufferImpl::height() { |
| - return cached_height_; |
| +void GLInProcessContext::SetContextLostCallback(Callback0::Type* callback) { |
| + context_lost_callback_.reset(callback); |
| } |
| -bool WebGraphicsContext3DInProcessCommandBufferImpl::isGLES2Compliant() { |
| - return is_gles2_; |
| +bool GLInProcessContext::MakeCurrent(GLInProcessContext* context) { |
| + if (context) { |
| + gles2::SetGLContext(context->gles2_implementation_); |
| + |
| + // Don't request latest error status from service. Just use the locally |
| + // cached information from the last flush. |
| + // TODO(apatrick): I'm not sure if this should actually change the |
| + // current context if it fails. For now it gets changed even if it fails |
| + // because making GL calls with a NULL context crashes. |
| + if (context->command_buffer_->GetState().error != ::gpu::error::kNoError) |
| + return false; |
| + } else { |
| + gles2::SetGLContext(NULL); |
| + } |
| + |
| + return true; |
| } |
| -WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::getPlatformTextureId() { |
| - return texture_; |
| +bool GLInProcessContext::SwapBuffers() { |
| + // Don't request latest error status from service. Just use the locally cached |
| + // information from the last flush. |
| + if (command_buffer_->GetState().error != ::gpu::error::kNoError) |
| + return false; |
| + |
| + gles2_implementation_->SwapBuffers(); |
| + gles2_implementation_->Finish(); |
| + return true; |
| } |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::prepareTexture() { |
| - if (!render_directly_to_web_view_) { |
| - // We need to prepare our rendering results for the compositor. |
| - makeContextCurrent(); |
| - ResolveMultisampledFramebuffer(0, 0, cached_width_, cached_height_); |
| +GLInProcessContext::Error GLInProcessContext::GetError() { |
| + CommandBuffer::State state = command_buffer_->GetState(); |
| + if (state.error == ::gpu::error::kNoError) { |
| + Error old_error = last_error_; |
| + last_error_ = SUCCESS; |
| + return old_error; |
| + } else { |
| + // All command buffer errors are unrecoverable. The error is treated as a |
| + // lost context: destroy the context and create another one. |
| + return CONTEXT_LOST; |
| } |
| } |
| -namespace { |
| +bool GLInProcessContext::IsCommandBufferContextLost() { |
| + CommandBuffer::State state = command_buffer_->GetState(); |
| + return state.error == ::gpu::error::kLostContext; |
| +} |
| -int CreateTextureObject(GLenum target) { |
| - GLuint texture = 0; |
| - glGenTextures(1, &texture); |
| - glBindTexture(target, texture); |
| - glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| - glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| - return texture; |
| +CommandBufferService* GLInProcessContext::GetCommandBufferService() { |
| + return command_buffer_.get(); |
| } |
| -} // anonymous namespace |
| +// TODO(gman): Remove This |
| +void GLInProcessContext::DisableShaderTranslation() { |
| + gles2_implementation_->CommandBufferEnableCHROMIUM( |
| + PEPPER3D_SKIP_GLSL_TRANSLATION); |
| +} |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::reshape(int width, int height) { |
| - cached_width_ = width; |
| - cached_height_ = height; |
| - makeContextCurrent(); |
| +GLES2Implementation* GLInProcessContext::GetImplementation() { |
| + return gles2_implementation_; |
| +} |
| - GLenum target = GL_TEXTURE_2D; |
| - |
| - if (!texture_) { |
| - // Generate the texture object |
| - texture_ = CreateTextureObject(target); |
| - // Generate the framebuffer object |
| - glGenFramebuffersEXT(1, &fbo_); |
| - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); |
| - bound_fbo_ = fbo_; |
| - if (attributes_.depth || attributes_.stencil) |
| - glGenRenderbuffersEXT(1, &depth_stencil_buffer_); |
| - // Generate the multisample framebuffer object |
| - if (attributes_.antialias) { |
| - glGenFramebuffersEXT(1, &multisample_fbo_); |
| - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, multisample_fbo_); |
| - bound_fbo_ = multisample_fbo_; |
| - glGenRenderbuffersEXT(1, &multisample_color_buffer_); |
| - if (attributes_.depth || attributes_.stencil) |
| - glGenRenderbuffersEXT(1, &multisample_depth_stencil_buffer_); |
| - } |
| - } |
| +GLInProcessContext::GLInProcessContext(GLInProcessContext* parent) |
| + : parent_(parent ? |
| + parent->AsWeakPtr() : base::WeakPtr<GLInProcessContext>()), |
| + parent_texture_id_(0), |
| + child_to_parent_latch_(kInvalidLatchId), |
| + parent_to_child_latch_(kInvalidLatchId), |
| + latch_transfer_buffer_id_(-1), |
| + gpu_scheduler_(NULL), |
| + gles2_helper_(NULL), |
| + transfer_buffer_id_(-1), |
| + gles2_implementation_(NULL), |
| + last_error_(SUCCESS) { |
| +} |
| - GLint internal_multisampled_color_format = 0; |
| - GLint internal_color_format = 0; |
| - GLint color_format = 0; |
| - GLint internal_depth_stencil_format = 0; |
| - if (attributes_.alpha) { |
| - // GL_RGBA8_OES == GL_RGBA8 |
| - internal_multisampled_color_format = GL_RGBA8; |
| - internal_color_format = is_gles2_ ? GL_RGBA : GL_RGBA8; |
| - color_format = GL_RGBA; |
| - } else { |
| - // GL_RGB8_OES == GL_RGB8 |
| - internal_multisampled_color_format = GL_RGB8; |
| - internal_color_format = is_gles2_ ? GL_RGB : GL_RGB8; |
| - color_format = GL_RGB; |
| +bool GLInProcessContext::Initialize(bool onscreen, |
| + gfx::PluginWindowHandle render_surface, |
| + const gfx::Size& size, |
| + const char* allowed_extensions, |
| + const int32* attrib_list, |
| + const GURL& active_url) { |
| + DCHECK(size.width() >= 0 && size.height() >= 0); |
| + |
| + // Ensure the gles2 library is initialized first in a thread safe way. |
| + g_gles2_initializer.Get(); |
| + |
| + // Allocate a frame buffer ID with respect to the parent. |
| + if (parent_.get()) { |
| + // Flush any remaining commands in the parent context to make sure the |
| + // texture id accounting stays consistent. |
| + int32 token = parent_->gles2_helper_->InsertToken(); |
| + parent_->gles2_helper_->WaitForToken(token); |
| + parent_texture_id_ = parent_->gles2_implementation_->MakeTextureId(); |
| } |
| - if (attributes_.stencil || attributes_.depth) { |
| - // We don't allow the logic where stencil is required and depth is not. |
| - // See GraphicsContext3DInternal constructor. |
| - if (attributes_.stencil && attributes_.depth) { |
| - internal_depth_stencil_format = GL_DEPTH24_STENCIL8_EXT; |
| - } else { |
| - if (is_gles2_) |
| - internal_depth_stencil_format = GL_DEPTH_COMPONENT16; |
| - else |
| - internal_depth_stencil_format = GL_DEPTH_COMPONENT; |
| + |
| + std::vector<int32> attribs; |
| + while (attrib_list) { |
| + int32 attrib = *attrib_list++; |
| + switch (attrib) { |
| + // Known attributes |
| + case ALPHA_SIZE: |
| + case BLUE_SIZE: |
| + case GREEN_SIZE: |
| + case RED_SIZE: |
| + case DEPTH_SIZE: |
| + case STENCIL_SIZE: |
| + case SAMPLES: |
| + case SAMPLE_BUFFERS: |
| + attribs.push_back(attrib); |
| + attribs.push_back(*attrib_list++); |
| + break; |
| + case NONE: |
| + attribs.push_back(attrib); |
| + attrib_list = NULL; |
| + break; |
| + default: |
| + last_error_ = BAD_ATTRIBUTE; |
| + attribs.push_back(NONE); |
| + attrib_list = NULL; |
| + break; |
| } |
| } |
| - bool must_restore_fbo = false; |
| + command_buffer_.reset(new CommandBufferService); |
| + if (!command_buffer_->Initialize(kCommandBufferSize)) |
| + return false; |
| + |
| + gpu_scheduler_ = new GpuScheduler(command_buffer_.get(), NULL); |
| - // Resize multisampling FBO |
| - if (attributes_.antialias) { |
| - GLint max_sample_count; |
| - glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count); |
| - GLint sample_count = std::min(8, max_sample_count); |
| - if (bound_fbo_ != multisample_fbo_) { |
| - must_restore_fbo = true; |
| - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, multisample_fbo_); |
| - } |
| - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, multisample_color_buffer_); |
| - if (have_ext_framebuffer_multisample_) { |
| - glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, |
| - sample_count, |
| - internal_multisampled_color_format, |
| - width, |
| - height); |
| + if (onscreen) { |
| + if (render_surface == gfx::kNullPluginWindow) { |
| + LOG(ERROR) << "Invalid surface handle for onscreen context."; |
| + command_buffer_.reset(); |
| } else { |
| - DCHECK(have_angle_framebuffer_multisample_); |
| - glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER_EXT, |
| - sample_count, |
| - internal_multisampled_color_format, |
| - width, |
| - height); |
| - } |
| - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, |
| - GL_COLOR_ATTACHMENT0_EXT, |
| - GL_RENDERBUFFER_EXT, |
| - multisample_color_buffer_); |
| - if (attributes_.stencil || attributes_.depth) { |
| - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, |
| - multisample_depth_stencil_buffer_); |
| - if (have_ext_framebuffer_multisample_) { |
| - glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, |
| - sample_count, |
| - internal_depth_stencil_format, |
| - width, |
| - height); |
| - } else { |
| - DCHECK(have_angle_framebuffer_multisample_); |
| - glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER_EXT, |
| - sample_count, |
| - internal_depth_stencil_format, |
| - width, |
| - height); |
| + if (!gpu_scheduler_->Initialize(render_surface, |
| + gfx::Size(), |
| + ::gpu::gles2::DisallowedExtensions(), |
| + allowed_extensions, |
| + attribs, |
| + NULL, |
| + 0)) { |
| + LOG(ERROR) << "Could not initialize GpuScheduler."; |
| + command_buffer_.reset(); |
| } |
| - if (attributes_.stencil) |
| - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, |
| - GL_STENCIL_ATTACHMENT_EXT, |
| - GL_RENDERBUFFER_EXT, |
| - multisample_depth_stencil_buffer_); |
| - if (attributes_.depth) |
| - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, |
| - GL_DEPTH_ATTACHMENT_EXT, |
| - GL_RENDERBUFFER_EXT, |
| - multisample_depth_stencil_buffer_); |
| } |
| - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); |
| - GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); |
| - if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { |
| - LOG(ERROR) << "Multisampling framebuffer was incomplete"; |
| + } else { |
| + GpuScheduler* parent_scheduler = |
| + parent_.get() ? parent_->gpu_scheduler_ : NULL; |
| + |
| + if (!gpu_scheduler_->Initialize(render_surface, |
| + size, |
| + ::gpu::gles2::DisallowedExtensions(), |
| + allowed_extensions, |
| + attribs, |
| + parent_scheduler, |
| + parent_texture_id_)) { |
| + LOG(ERROR) << "Could not initialize offscreen GpuScheduler."; |
| + command_buffer_.reset(); |
| + } |
| + } |
| + if (!command_buffer_.get()) { |
| + Destroy(); |
| + return false; |
| + } |
| + |
| + command_buffer_->SetPutOffsetChangeCallback( |
| + NewCallback(gpu_scheduler_, &GpuScheduler::PutChanged)); |
| - // FIXME: cleanup. |
| - NOTIMPLEMENTED(); |
| + // Create the GLES2 helper, which writes the command buffer protocol. |
| + gles2_helper_ = new GLES2CmdHelper(command_buffer_.get()); |
| + if (!gles2_helper_->Initialize(kCommandBufferSize)) { |
| + Destroy(); |
| + return false; |
| + } |
| + |
| + // Create a transfer buffer used to copy resources between the renderer |
| + // process and the GPU process. |
|
jamesr
2011/06/01 02:07:02
comment isn't quite correct for this case. what i
greggman
2011/06/01 21:55:39
Done.
|
| + transfer_buffer_id_ = |
| + command_buffer_->CreateTransferBuffer( |
| + kTransferBufferSize, ::gpu::kCommandBufferSharedMemoryId); |
| + if (transfer_buffer_id_ < 0) { |
| + Destroy(); |
| + return false; |
| + } |
| + |
| + // Map the buffer into the renderer process's address space. |
| + Buffer transfer_buffer = |
| + command_buffer_->GetTransferBuffer(transfer_buffer_id_); |
|
jamesr
2011/06/01 02:07:02
this is a no-op for this case right?
greggman
2011/06/01 21:55:39
I don't actually know and I shouldn't have to. I w
|
| + if (!transfer_buffer.ptr) { |
| + Destroy(); |
| + return false; |
| + } |
| + |
| + // Register transfer buffer so that the context can access latches. |
|
jamesr
2011/06/01 02:07:02
comment is misleading
greggman
2011/06/01 21:55:39
Done.
|
| +// LatchAllocator* latch_shm = LatchAllocator::GetInstance(); |
| +// latch_transfer_buffer_id_ = command_buffer_->RegisterTransferBuffer( |
|
jamesr
2011/06/01 02:07:02
what does this really do?
greggman
2011/06/01 21:55:39
This code has been deleted.
|
| +// latch_shm->shared_memory(), LatchAllocator::size(), |
| +// ::gpu::kLatchSharedMemoryId); |
| +// if (latch_transfer_buffer_id_ != ::gpu::kLatchSharedMemoryId) { |
| +// Destroy(); |
| +// return false; |
| +// } |
| + |
| + // If this is a child context, setup latches for synchronization between child |
| + // and parent. |
| + if (parent_.get()) { |
| + if (!CreateLatch(&child_to_parent_latch_) || |
| + !CreateLatch(&parent_to_child_latch_)) { |
| + Destroy(); |
| + return false; |
| } |
| } |
| - // Resize regular FBO |
| - if (bound_fbo_ != fbo_) { |
| - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); |
| - must_restore_fbo = true; |
| + // Create the object exposing the OpenGL API. |
| + gles2_implementation_ = new GLES2Implementation( |
| + gles2_helper_, |
| + transfer_buffer.size, |
| + transfer_buffer.ptr, |
| + transfer_buffer_id_, |
| + false); |
| + |
| + size_ = size; |
| + |
| + return true; |
| +} |
| + |
| +void GLInProcessContext::Destroy() { |
| + if (parent_.get() && parent_texture_id_ != 0) { |
| + parent_->gles2_implementation_->FreeTextureId(parent_texture_id_); |
| + parent_texture_id_ = 0; |
| + } |
| + |
| + delete gles2_implementation_; |
| + gles2_implementation_ = NULL; |
| + |
| + if (child_to_parent_latch_ != kInvalidLatchId) { |
| + DestroyLatch(child_to_parent_latch_); |
| + child_to_parent_latch_ = kInvalidLatchId; |
| } |
| - glBindTexture(target, texture_); |
| - glTexImage2D(target, 0, internal_color_format, |
| - width, height, |
| - 0, color_format, GL_UNSIGNED_BYTE, 0); |
| - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, |
| - GL_COLOR_ATTACHMENT0_EXT, |
| - target, |
| - texture_, |
| - 0); |
| - glBindTexture(target, 0); |
| - if (!attributes_.antialias && (attributes_.stencil || attributes_.depth)) { |
| - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil_buffer_); |
| - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, |
| - internal_depth_stencil_format, |
| - width, height); |
| - if (attributes_.stencil) |
| - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, |
| - GL_STENCIL_ATTACHMENT_EXT, |
| - GL_RENDERBUFFER_EXT, |
| - depth_stencil_buffer_); |
| - if (attributes_.depth) |
| - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, |
| - GL_DEPTH_ATTACHMENT_EXT, |
| - GL_RENDERBUFFER_EXT, |
| - depth_stencil_buffer_); |
| - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); |
| + if (parent_to_child_latch_ != kInvalidLatchId) { |
| + DestroyLatch(parent_to_child_latch_); |
| + parent_to_child_latch_ = kInvalidLatchId; |
| + } |
| + if (command_buffer_.get() && latch_transfer_buffer_id_ != -1) { |
| + command_buffer_->DestroyTransferBuffer(latch_transfer_buffer_id_); |
| + latch_transfer_buffer_id_ = -1; |
| } |
| - GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); |
| - if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { |
| - LOG(ERROR) << "Framebuffer was incomplete"; |
| - // FIXME: cleanup. |
| - NOTIMPLEMENTED(); |
| + if (command_buffer_.get() && transfer_buffer_id_ != -1) { |
| + command_buffer_->DestroyTransferBuffer(transfer_buffer_id_); |
| + transfer_buffer_id_ = -1; |
| } |
| - if (attributes_.antialias) { |
| - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, multisample_fbo_); |
| - if (bound_fbo_ == multisample_fbo_) |
| - must_restore_fbo = false; |
| + delete gles2_helper_; |
| + gles2_helper_ = NULL; |
| + |
| + command_buffer_.reset(); |
| +} |
| + |
| +void GLInProcessContext::OnSwapBuffers() { |
| + if (swap_buffers_callback_.get()) |
| + swap_buffers_callback_->Run(); |
| +} |
| + |
| +void GLInProcessContext::OnContextLost() { |
| + if (context_lost_callback_.get()) |
| + context_lost_callback_->Run(); |
| +} |
| + |
| +bool GLInProcessContext::CreateLatch(uint32* ret_latch) { |
| + return LatchAllocator::GetInstance()->AllocateLatch(ret_latch); |
| +} |
| + |
| +bool GLInProcessContext::DestroyLatch(uint32 latch) { |
| + return LatchAllocator::GetInstance()->FreeLatch(latch); |
| +} |
| + |
| +bool GLInProcessContext::GetParentToChildLatch(uint32* parent_to_child_latch) { |
| + if (parent_.get()) { |
| + *parent_to_child_latch = parent_to_child_latch_; |
| + return true; |
| } |
| + return false; |
| +} |
| - // Initialize renderbuffers to 0. |
| - GLfloat clearColor[] = {0, 0, 0, 0}, clearDepth = 0; |
| - GLint clearStencil = 0; |
| - GLboolean colorMask[] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE}; |
| - GLboolean depthMask = GL_TRUE; |
| - GLuint stencilMask = 0xffffffff; |
| - GLboolean isScissorEnabled = GL_FALSE; |
| - GLboolean isDitherEnabled = GL_FALSE; |
| - GLbitfield clearMask = GL_COLOR_BUFFER_BIT; |
| - glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor); |
| - glClearColor(0, 0, 0, 0); |
| - glGetBooleanv(GL_COLOR_WRITEMASK, colorMask); |
| - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
| - if (attributes_.depth) { |
| - glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth); |
| - glClearDepth(1); |
| - glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask); |
| - glDepthMask(GL_TRUE); |
| - clearMask |= GL_DEPTH_BUFFER_BIT; |
| +bool GLInProcessContext::GetChildToParentLatch(uint32* child_to_parent_latch) { |
| + if (parent_.get()) { |
| + *child_to_parent_latch = child_to_parent_latch_; |
| + return true; |
| } |
| - if (attributes_.stencil) { |
| - glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &clearStencil); |
| - glClearStencil(0); |
| - glGetIntegerv(GL_STENCIL_WRITEMASK, |
| - reinterpret_cast<GLint*>(&stencilMask)); |
| - glStencilMaskSeparate(GL_FRONT, 0xffffffff); |
| - clearMask |= GL_STENCIL_BUFFER_BIT; |
| + return false; |
| +} |
| + |
| +WebGraphicsContext3DInProcessCommandBufferImpl::WebGraphicsContext3DInProcessCommandBufferImpl() |
| + : context_(NULL), |
| + gl_(NULL), |
| + web_view_(NULL), |
| +#if defined(OS_MACOSX) |
| + plugin_handle_(NULL), |
| +#endif // defined(OS_MACOSX) |
| + context_lost_callback_(0), |
| + cached_width_(0), |
| + cached_height_(0), |
| + bound_fbo_(0) { |
| +} |
| + |
| +WebGraphicsContext3DInProcessCommandBufferImpl:: |
| + ~WebGraphicsContext3DInProcessCommandBufferImpl() { |
| +} |
| + |
| +// This string should only be passed for WebGL contexts. Nothing ELSE!!! |
| +// Compositor contexts, Canvas2D contexts, Pepper Contexts, nor any other use of |
| +// a context should not pass this string. |
| +static const char* kWebGLPreferredGLExtensions = |
| + "GL_OES_packed_depth_stencil " |
| + "GL_OES_depth24 " |
| + "GL_CHROMIUM_webglsl"; |
| + |
| +bool WebGraphicsContext3DInProcessCommandBufferImpl::initialize( |
| + WebGraphicsContext3D::Attributes attributes, |
| + WebKit::WebView* web_view, |
| + bool render_directly_to_web_view) { |
| + webkit_glue::BindSkiaToCommandBufferGL(); |
| + |
| + // Convert WebGL context creation attributes into GLInProcessContext / EGL |
| + // size requests. |
| + const int alpha_size = attributes.alpha ? 8 : 0; |
| + const int depth_size = attributes.depth ? 24 : 0; |
| + const int stencil_size = attributes.stencil ? 8 : 0; |
| + const int samples = attributes.antialias ? 4 : 0; |
| + const int sample_buffers = attributes.antialias ? 1 : 0; |
| + const int32 attribs[] = { |
| + GLInProcessContext::ALPHA_SIZE, alpha_size, |
| + GLInProcessContext::DEPTH_SIZE, depth_size, |
| + GLInProcessContext::STENCIL_SIZE, stencil_size, |
| + GLInProcessContext::SAMPLES, samples, |
| + GLInProcessContext::SAMPLE_BUFFERS, sample_buffers, |
| + GLInProcessContext::NONE, |
| + }; |
| + |
| + const char* preferred_extensions = attributes.noExtensions ? |
| + kWebGLPreferredGLExtensions : "*"; |
| + |
| + GURL active_url; |
| + if (web_view && web_view->mainFrame()) |
| + active_url = GURL(web_view->mainFrame()->url()); |
| + |
| + GLInProcessContext* parent_context = NULL; |
| + if (!render_directly_to_web_view) { |
| + WebKit::WebGraphicsContext3D* view_context = |
| + web_view->graphicsContext3D(); |
| + if (view_context) { |
| + WebGraphicsContext3DInProcessCommandBufferImpl* context_impl = |
| + static_cast<WebGraphicsContext3DInProcessCommandBufferImpl*>( |
| + view_context); |
| + parent_context = context_impl->context_; |
| + } else { |
| + NOTREACHED() << "no parent context."; |
| + } |
| } |
| - isScissorEnabled = glIsEnabled(GL_SCISSOR_TEST); |
| - glDisable(GL_SCISSOR_TEST); |
| - isDitherEnabled = glIsEnabled(GL_DITHER); |
| - glDisable(GL_DITHER); |
| - |
| - glClear(clearMask); |
| - |
| - glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); |
| - glColorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]); |
| - if (attributes_.depth) { |
| - glClearDepth(clearDepth); |
| - glDepthMask(depthMask); |
| + |
| + context_ = GLInProcessContext::CreateOffscreenContext( |
| + parent_context, |
| + gfx::Size(1, 1), |
| + preferred_extensions, |
| + attribs, |
| + active_url); |
| + web_view_ = NULL; |
| + |
| + if (!context_) |
| + return false; |
| + |
| + gl_ = context_->GetImplementation(); |
| + context_->SetContextLostCallback( |
| + NewCallback( |
| + this, |
| + &WebGraphicsContext3DInProcessCommandBufferImpl::OnContextLost)); |
| + |
| + // Set attributes_ from created offscreen context. |
| + { |
| + attributes_ = attributes; |
| + GLint alpha_bits = 0; |
| + getIntegerv(GL_ALPHA_BITS, &alpha_bits); |
| + attributes_.alpha = alpha_bits > 0; |
| + GLint depth_bits = 0; |
| + getIntegerv(GL_DEPTH_BITS, &depth_bits); |
| + attributes_.depth = depth_bits > 0; |
| + GLint stencil_bits = 0; |
| + getIntegerv(GL_STENCIL_BITS, &stencil_bits); |
| + attributes_.stencil = stencil_bits > 0; |
| + GLint samples = 0; |
| + getIntegerv(GL_SAMPLES, &samples); |
| + attributes_.antialias = samples > 0; |
| } |
| - if (attributes_.stencil) { |
| - glClearStencil(clearStencil); |
| - glStencilMaskSeparate(GL_FRONT, stencilMask); |
| + makeContextCurrent(); |
| + |
| + return true; |
| +} |
| + |
| +bool WebGraphicsContext3DInProcessCommandBufferImpl::makeContextCurrent() { |
| + return GLInProcessContext::MakeCurrent(context_); |
| +} |
| + |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::ClearContext() { |
| + // Comment the next line in to help find missing MakeCurrent calls |
| + // in code not going through WebGraphicsContext3D. |
| + // GLInProcessContext::MakeCurrent(NULL); |
|
jamesr
2011/06/01 02:07:02
comment and code are out of sync
greggman
2011/06/01 21:55:39
I updated the comment though it still says basical
|
| +} |
| + |
| +int WebGraphicsContext3DInProcessCommandBufferImpl::width() { |
| + return cached_width_; |
| +} |
| + |
| +int WebGraphicsContext3DInProcessCommandBufferImpl::height() { |
| + return cached_height_; |
| +} |
| + |
| +bool WebGraphicsContext3DInProcessCommandBufferImpl::isGLES2Compliant() { |
| + return true; |
| +} |
| + |
| +WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::getPlatformTextureId() { |
| + DCHECK(context_); |
| + return context_->GetParentTextureId(); |
| +} |
| + |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::prepareTexture() { |
| + // Copies the contents of the off-screen render target into the texture |
| + // used by the compositor. |
| + context_->SwapBuffers(); |
| +} |
| + |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::reshape( |
| + int width, int height) { |
| + cached_width_ = width; |
| + cached_height_ = height; |
| + |
| + ClearContext(); |
| + |
| + if (web_view_) { |
| +#if defined(OS_MACOSX) |
| + context_->ResizeOnscreen(gfx::Size(width, height)); |
| +#else |
| + gl_->ResizeCHROMIUM(width, height); |
| +#endif |
| + } else { |
| + context_->ResizeOffscreen(gfx::Size(width, height)); |
| + // Force a SwapBuffers to get the framebuffer to resize. |
| + context_->SwapBuffers(); |
| } |
| - if (isScissorEnabled) |
| - glEnable(GL_SCISSOR_TEST); |
| - else |
| - glDisable(GL_SCISSOR_TEST); |
| - if (isDitherEnabled) |
| - glEnable(GL_DITHER); |
| - else |
| - glDisable(GL_DITHER); |
| - |
| - if (must_restore_fbo) |
| - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); |
| #ifdef FLIP_FRAMEBUFFER_VERTICALLY |
| - if (scanline_) { |
| - delete[] scanline_; |
| - scanline_ = 0; |
| - } |
| - scanline_ = new unsigned char[width * 4]; |
| + scanline_.reset(new uint8[width * 4]); |
| #endif // FLIP_FRAMEBUFFER_VERTICALLY |
| } |
| +WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createCompositorTexture( |
| + WGC3Dsizei width, WGC3Dsizei height) { |
| + ClearContext(); |
| + return context_->CreateParentTexture(gfx::Size(width, height)); |
| +} |
| + |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::deleteCompositorTexture( |
| + WebGLId parent_texture) { |
| + ClearContext(); |
| + context_->DeleteParentTexture(parent_texture); |
| +} |
| + |
| #ifdef FLIP_FRAMEBUFFER_VERTICALLY |
| void WebGraphicsContext3DInProcessCommandBufferImpl::FlipVertically( |
| - unsigned char* framebuffer, unsigned int width, unsigned int height) { |
| - unsigned char* scanline = scanline_; |
| + uint8* framebuffer, |
| + unsigned int width, |
| + unsigned int height) { |
| + uint8* scanline = scanline_.get(); |
| if (!scanline) |
| return; |
| unsigned int row_bytes = width * 4; |
| unsigned int count = height / 2; |
| for (unsigned int i = 0; i < count; i++) { |
| - unsigned char* row_a = framebuffer + i * row_bytes; |
| - unsigned char* row_b = framebuffer + (height - i - 1) * row_bytes; |
| - // FIXME: this is where the multiplication of the alpha |
| + uint8* row_a = framebuffer + i * row_bytes; |
| + uint8* row_b = framebuffer + (height - i - 1) * row_bytes; |
| + // TODO(kbr): this is where the multiplication of the alpha |
| // channel into the color buffer will need to occur if the |
| // user specifies the "premultiplyAlpha" flag in the context |
| // creation attributes. |
| @@ -581,11 +925,12 @@ void WebGraphicsContext3DInProcessCommandBufferImpl::FlipVertically( |
| #endif |
| bool WebGraphicsContext3DInProcessCommandBufferImpl::readBackFramebuffer( |
| - unsigned char* pixels, size_t bufferSize) { |
| - if (bufferSize != static_cast<size_t>(4 * width() * height())) |
| + unsigned char* pixels, |
| + size_t buffer_size) { |
| + ClearContext(); |
| + if (buffer_size != static_cast<size_t>(4 * width() * height())) { |
| return false; |
| - |
| - makeContextCurrent(); |
| + } |
| // Earlier versions of this code used the GPU to flip the |
| // framebuffer vertically before reading it back for compositing |
| @@ -594,263 +939,271 @@ bool WebGraphicsContext3DInProcessCommandBufferImpl::readBackFramebuffer( |
| // vertical flip is only a temporary solution anyway until Chrome |
| // is fully GPU composited, it wasn't worth the complexity. |
| - ResolveMultisampledFramebuffer(0, 0, cached_width_, cached_height_); |
| - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); |
| - |
| - GLint pack_alignment = 4; |
| - bool must_restore_pack_alignment = false; |
| - glGetIntegerv(GL_PACK_ALIGNMENT, &pack_alignment); |
| - if (pack_alignment > 4) { |
| - glPixelStorei(GL_PACK_ALIGNMENT, 4); |
| - must_restore_pack_alignment = true; |
| + bool mustRestoreFBO = (bound_fbo_ != 0); |
| + if (mustRestoreFBO) { |
| + gl_->BindFramebuffer(GL_FRAMEBUFFER, 0); |
| } |
| + gl_->ReadPixels(0, 0, cached_width_, cached_height_, |
| + GL_RGBA, GL_UNSIGNED_BYTE, pixels); |
| - if (is_gles2_) { |
| - // FIXME: consider testing for presence of GL_OES_read_format |
| - // and GL_EXT_read_format_bgra, and using GL_BGRA_EXT here |
| - // directly. |
| - glReadPixels(0, 0, cached_width_, cached_height_, |
| - GL_RGBA, GL_UNSIGNED_BYTE, pixels); |
| - for (size_t i = 0; i < bufferSize; i += 4) { |
| - std::swap(pixels[i], pixels[i + 2]); |
| - } |
| - } else { |
| - glReadPixels(0, 0, cached_width_, cached_height_, |
| - GL_BGRA, GL_UNSIGNED_BYTE, pixels); |
| + // Swizzle red and blue channels |
| + // TODO(kbr): expose GL_BGRA as extension |
| + for (size_t i = 0; i < buffer_size; i += 4) { |
| + std::swap(pixels[i], pixels[i + 2]); |
| } |
| - if (must_restore_pack_alignment) |
| - glPixelStorei(GL_PACK_ALIGNMENT, pack_alignment); |
| - |
| - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); |
| + if (mustRestoreFBO) { |
| + gl_->BindFramebuffer(GL_FRAMEBUFFER, bound_fbo_); |
| + } |
| #ifdef FLIP_FRAMEBUFFER_VERTICALLY |
| - if (pixels) |
| + if (pixels) { |
| FlipVertically(pixels, cached_width_, cached_height_); |
| + } |
| #endif |
| return true; |
| } |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::synthesizeGLError(WGC3Denum error) { |
| - if (synthetic_errors_set_.find(error) == synthetic_errors_set_.end()) { |
| - synthetic_errors_set_.insert(error); |
| - synthetic_errors_list_.push_back(error); |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::synthesizeGLError( |
| + WGC3Denum error) { |
| + if (find(synthetic_errors_.begin(), synthetic_errors_.end(), error) == |
| + synthetic_errors_.end()) { |
| + synthetic_errors_.push_back(error); |
| } |
| } |
| void* WebGraphicsContext3DInProcessCommandBufferImpl::mapBufferSubDataCHROMIUM( |
| - WGC3Denum target, WGC3Dintptr offset, |
| - WGC3Dsizeiptr size, WGC3Denum access) { |
| - return 0; |
| + WGC3Denum target, |
| + WGC3Dintptr offset, |
| + WGC3Dsizeiptr size, |
| + WGC3Denum access) { |
| + ClearContext(); |
| + return gl_->MapBufferSubDataCHROMIUM(target, offset, size, access); |
| } |
| void WebGraphicsContext3DInProcessCommandBufferImpl::unmapBufferSubDataCHROMIUM( |
| const void* mem) { |
| + ClearContext(); |
| + return gl_->UnmapBufferSubDataCHROMIUM(mem); |
| } |
| void* WebGraphicsContext3DInProcessCommandBufferImpl::mapTexSubImage2DCHROMIUM( |
| - WGC3Denum target, WGC3Dint level, WGC3Dint xoffset, WGC3Dint yoffset, |
| - WGC3Dsizei width, WGC3Dsizei height, WGC3Denum format, WGC3Denum type, |
| + WGC3Denum target, |
| + WGC3Dint level, |
| + WGC3Dint xoffset, |
| + WGC3Dint yoffset, |
| + WGC3Dsizei width, |
| + WGC3Dsizei height, |
| + WGC3Denum format, |
| + WGC3Denum type, |
| WGC3Denum access) { |
| - return 0; |
| + ClearContext(); |
| + return gl_->MapTexSubImage2DCHROMIUM( |
| + target, level, xoffset, yoffset, width, height, format, type, access); |
| } |
| void WebGraphicsContext3DInProcessCommandBufferImpl::unmapTexSubImage2DCHROMIUM( |
| const void* mem) { |
| + ClearContext(); |
| + gl_->UnmapTexSubImage2DCHROMIUM(mem); |
| } |
| void WebGraphicsContext3DInProcessCommandBufferImpl::copyTextureToParentTextureCHROMIUM( |
| - WebGLId id, WebGLId id2) { |
| - if (!glGetTexLevelParameteriv) |
| - return; |
| - |
| - makeContextCurrent(); |
| - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, copy_texture_to_parent_texture_fbo_); |
| - glFramebufferTexture2DEXT(GL_FRAMEBUFFER, |
| - GL_COLOR_ATTACHMENT0, |
| - GL_TEXTURE_2D, |
| - id, |
| - 0); // level |
| - glBindTexture(GL_TEXTURE_2D, id2); |
| - GLsizei width, height; |
| - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); |
| - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); |
| - glCopyTexImage2D(GL_TEXTURE_2D, |
| - 0, // level |
| - GL_RGBA, |
| - 0, 0, // x, y |
| - width, |
| - height, |
| - 0); // border |
| - glBindTexture(GL_TEXTURE_2D, bound_texture_); |
| - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); |
| + WebGLId texture, WebGLId parentTexture) { |
| + ClearContext(); |
| + copyTextureToCompositor(texture, parentTexture); |
| } |
| void WebGraphicsContext3DInProcessCommandBufferImpl::getParentToChildLatchCHROMIUM( |
| WGC3Duint* latch_id) |
| { |
| + ClearContext(); |
| + if (!context_->GetParentToChildLatch(latch_id)) { |
| + LOG(ERROR) << "getLatch must only be called on child context"; |
| + synthesizeGLError(GL_INVALID_OPERATION); |
| + *latch_id = ::gpu::kInvalidLatchId; |
| + } |
| } |
| void WebGraphicsContext3DInProcessCommandBufferImpl::getChildToParentLatchCHROMIUM( |
| WGC3Duint* latch_id) |
| { |
| + ClearContext(); |
| + if (!context_->GetChildToParentLatch(latch_id)) { |
| + LOG(ERROR) << "getLatch must only be called on child context"; |
| + synthesizeGLError(GL_INVALID_OPERATION); |
| + *latch_id = ::gpu::kInvalidLatchId; |
| + } |
| } |
| void WebGraphicsContext3DInProcessCommandBufferImpl::waitLatchCHROMIUM( |
| WGC3Duint latch_id) |
| { |
| + ClearContext(); |
| + gl_->WaitLatchCHROMIUM(latch_id); |
| } |
| void WebGraphicsContext3DInProcessCommandBufferImpl::setLatchCHROMIUM( |
| WGC3Duint latch_id) |
| { |
| + ClearContext(); |
| + gl_->SetLatchCHROMIUM(latch_id); |
| + // required to ensure set command is sent to GPU process |
| + gl_->Flush(); |
| } |
| -WebString WebGraphicsContext3DInProcessCommandBufferImpl:: |
| +void WebGraphicsContext3DInProcessCommandBufferImpl:: |
| + rateLimitOffscreenContextCHROMIUM() { |
| + ClearContext(); |
| + gl_->RateLimitOffscreenContextCHROMIUM(); |
| +} |
| + |
| +WebKit::WebString WebGraphicsContext3DInProcessCommandBufferImpl:: |
| getRequestableExtensionsCHROMIUM() { |
| - return WebString(); |
| + ClearContext(); |
| + return WebKit::WebString::fromUTF8( |
| + gl_->GetRequestableExtensionsCHROMIUM()); |
| } |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::requestExtensionCHROMIUM(const char*) { |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::requestExtensionCHROMIUM( |
| + const char* extension) { |
| + ClearContext(); |
| + gl_->RequestExtensionCHROMIUM(extension); |
| } |
| void WebGraphicsContext3DInProcessCommandBufferImpl::blitFramebufferCHROMIUM( |
| WGC3Dint srcX0, WGC3Dint srcY0, WGC3Dint srcX1, WGC3Dint srcY1, |
| WGC3Dint dstX0, WGC3Dint dstY0, WGC3Dint dstX1, WGC3Dint dstY1, |
| WGC3Dbitfield mask, WGC3Denum filter) { |
| + ClearContext(); |
| + gl_->BlitFramebufferEXT( |
| + srcX0, srcY0, srcX1, srcY1, |
| + dstX0, dstY0, dstX1, dstY1, |
| + mask, filter); |
| } |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::renderbufferStorageMultisampleCHROMIUM( |
| - WGC3Denum target, WGC3Dsizei samples, WGC3Denum internalformat, |
| - WGC3Dsizei width, WGC3Dsizei height) { |
| +void WebGraphicsContext3DInProcessCommandBufferImpl:: |
| + renderbufferStorageMultisampleCHROMIUM( |
| + WGC3Denum target, WGC3Dsizei samples, WGC3Denum internalformat, |
| + WGC3Dsizei width, WGC3Dsizei height) { |
| + ClearContext(); |
| + gl_->RenderbufferStorageMultisampleEXT( |
| + target, samples, internalformat, width, height); |
| } |
| // Helper macros to reduce the amount of code. |
| -#define DELEGATE_TO_GL(name, glname) \ |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::name() { \ |
| - makeContextCurrent(); \ |
| - gl##glname(); \ |
| +#define DELEGATE_TO_GL(name, glname) \ |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::name() { \ |
| + ClearContext(); \ |
| + gl_->glname(); \ |
| } |
| -#define DELEGATE_TO_GL_1(name, glname, t1) \ |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1) { \ |
| - makeContextCurrent(); \ |
| - gl##glname(a1); \ |
| +#define DELEGATE_TO_GL_1(name, glname, t1) \ |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1) { \ |
| + ClearContext(); \ |
| + gl_->glname(a1); \ |
| } |
| -#define DELEGATE_TO_GL_1R(name, glname, t1, rt) \ |
| -rt WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1) { \ |
| - makeContextCurrent(); \ |
| - return gl##glname(a1); \ |
| +#define DELEGATE_TO_GL_1R(name, glname, t1, rt) \ |
| +rt WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1) { \ |
| + ClearContext(); \ |
| + return gl_->glname(a1); \ |
| } |
| -#define DELEGATE_TO_GL_1RB(name, glname, t1, rt) \ |
| -rt WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1) { \ |
| - makeContextCurrent(); \ |
| - return gl##glname(a1) ? true : false; \ |
| +#define DELEGATE_TO_GL_1RB(name, glname, t1, rt) \ |
| +rt WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1) { \ |
| + ClearContext(); \ |
| + return gl_->glname(a1) ? true : false; \ |
| } |
| -#define DELEGATE_TO_GL_2(name, glname, t1, t2) \ |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1, t2 a2) { \ |
| - makeContextCurrent(); \ |
| - gl##glname(a1, a2); \ |
| +#define DELEGATE_TO_GL_2(name, glname, t1, t2) \ |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ |
| + t1 a1, t2 a2) { \ |
| + ClearContext(); \ |
| + gl_->glname(a1, a2); \ |
| } |
| -#define DELEGATE_TO_GL_2R(name, glname, t1, t2, rt) \ |
| -rt WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1, t2 a2) { \ |
| - makeContextCurrent(); \ |
| - return gl##glname(a1, a2); \ |
| +#define DELEGATE_TO_GL_2R(name, glname, t1, t2, rt) \ |
| +rt WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1, t2 a2) { \ |
| + ClearContext(); \ |
| + return gl_->glname(a1, a2); \ |
| } |
| -#define DELEGATE_TO_GL_3(name, glname, t1, t2, t3) \ |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1, t2 a2, t3 a3) { \ |
| - makeContextCurrent(); \ |
| - gl##glname(a1, a2, a3); \ |
| +#define DELEGATE_TO_GL_3(name, glname, t1, t2, t3) \ |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ |
| + t1 a1, t2 a2, t3 a3) { \ |
| + ClearContext(); \ |
| + gl_->glname(a1, a2, a3); \ |
| } |
| -#define DELEGATE_TO_GL_4(name, glname, t1, t2, t3, t4) \ |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, t4 a4) { \ |
| - makeContextCurrent(); \ |
| - gl##glname(a1, a2, a3, a4); \ |
| +#define DELEGATE_TO_GL_4(name, glname, t1, t2, t3, t4) \ |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ |
| + t1 a1, t2 a2, t3 a3, t4 a4) { \ |
| + ClearContext(); \ |
| + gl_->glname(a1, a2, a3, a4); \ |
| } |
| -#define DELEGATE_TO_GL_5(name, glname, t1, t2, t3, t4, t5) \ |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, \ |
| - t5 a5) { \ |
| - makeContextCurrent(); \ |
| - gl##glname(a1, a2, a3, a4, a5); \ |
| +#define DELEGATE_TO_GL_5(name, glname, t1, t2, t3, t4, t5) \ |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ |
| + t1 a1, t2 a2, t3 a3, \ |
| + t4 a4, t5 a5) { \ |
| + ClearContext(); \ |
| + gl_->glname(a1, a2, a3, a4, a5); \ |
| } |
| -#define DELEGATE_TO_GL_6(name, glname, t1, t2, t3, t4, t5, t6) \ |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, \ |
| - t5 a5, t6 a6) { \ |
| - makeContextCurrent(); \ |
| - gl##glname(a1, a2, a3, a4, a5, a6); \ |
| +#define DELEGATE_TO_GL_6(name, glname, t1, t2, t3, t4, t5, t6) \ |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ |
| + t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) { \ |
| + ClearContext(); \ |
| + gl_->glname(a1, a2, a3, a4, a5, a6); \ |
| } |
| -#define DELEGATE_TO_GL_7(name, glname, t1, t2, t3, t4, t5, t6, t7) \ |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, \ |
| - t5 a5, t6 a6, t7 a7) { \ |
| - makeContextCurrent(); \ |
| - gl##glname(a1, a2, a3, a4, a5, a6, a7); \ |
| +#define DELEGATE_TO_GL_7(name, glname, t1, t2, t3, t4, t5, t6, t7) \ |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ |
| + t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7) { \ |
| + ClearContext(); \ |
| + gl_->glname(a1, a2, a3, a4, a5, a6, a7); \ |
| } |
| -#define DELEGATE_TO_GL_8(name, glname, t1, t2, t3, t4, t5, t6, t7, t8) \ |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, \ |
| - t5 a5, t6 a6, t7 a7, t8 a8) { \ |
| - makeContextCurrent(); \ |
| - gl##glname(a1, a2, a3, a4, a5, a6, a7, a8); \ |
| +#define DELEGATE_TO_GL_8(name, glname, t1, t2, t3, t4, t5, t6, t7, t8) \ |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ |
| + t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7, t8 a8) { \ |
| + ClearContext(); \ |
| + gl_->glname(a1, a2, a3, a4, a5, a6, a7, a8); \ |
| } |
| -#define DELEGATE_TO_GL_9(name, glname, t1, t2, t3, t4, t5, t6, t7, t8, t9) \ |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, \ |
| - t5 a5, t6 a6, t7 a7, t8 a8, \ |
| - t9 a9) { \ |
| - makeContextCurrent(); \ |
| - gl##glname(a1, a2, a3, a4, a5, a6, a7, a8, a9); \ |
| +#define DELEGATE_TO_GL_9(name, glname, t1, t2, t3, t4, t5, t6, t7, t8, t9) \ |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ |
| + t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7, t8 a8, t9 a9) { \ |
| + ClearContext(); \ |
| + gl_->glname(a1, a2, a3, a4, a5, a6, a7, a8, a9); \ |
| } |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::activeTexture(WGC3Denum texture) { |
| - // FIXME: query number of textures available. |
| - if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0+32) |
| - // FIXME: raise exception. |
| - return; |
| - |
| - makeContextCurrent(); |
| - glActiveTexture(texture); |
| -} |
| +DELEGATE_TO_GL_1(activeTexture, ActiveTexture, WGC3Denum) |
| DELEGATE_TO_GL_2(attachShader, AttachShader, WebGLId, WebGLId) |
| -DELEGATE_TO_GL_3(bindAttribLocation, BindAttribLocation, |
| - WebGLId, WGC3Duint, const WGC3Dchar*) |
| +DELEGATE_TO_GL_3(bindAttribLocation, BindAttribLocation, WebGLId, |
| + WGC3Duint, const WGC3Dchar*) |
| -DELEGATE_TO_GL_2(bindBuffer, BindBuffer, WGC3Denum, WebGLId); |
| +DELEGATE_TO_GL_2(bindBuffer, BindBuffer, WGC3Denum, WebGLId) |
| void WebGraphicsContext3DInProcessCommandBufferImpl::bindFramebuffer( |
| - WGC3Denum target, WebGLId framebuffer) { |
| - makeContextCurrent(); |
| - if (!framebuffer) |
| - framebuffer = (attributes_.antialias ? multisample_fbo_ : fbo_); |
| - if (framebuffer != bound_fbo_) { |
| - glBindFramebufferEXT(target, framebuffer); |
| - bound_fbo_ = framebuffer; |
| - } |
| + WGC3Denum target, |
| + WebGLId framebuffer) { |
| + ClearContext(); |
| + gl_->BindFramebuffer(target, framebuffer); |
| + bound_fbo_ = framebuffer; |
| } |
| -DELEGATE_TO_GL_2(bindRenderbuffer, BindRenderbufferEXT, WGC3Denum, WebGLId) |
| +DELEGATE_TO_GL_2(bindRenderbuffer, BindRenderbuffer, WGC3Denum, WebGLId) |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::bindTexture( |
| - WGC3Denum target, WebGLId texture) { |
| - makeContextCurrent(); |
| - glBindTexture(target, texture); |
| - bound_texture_ = texture; |
| -} |
| +DELEGATE_TO_GL_2(bindTexture, BindTexture, WGC3Denum, WebGLId) |
| DELEGATE_TO_GL_4(blendColor, BlendColor, |
| - WGC3Dfloat, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) |
| + WGC3Dclampf, WGC3Dclampf, WGC3Dclampf, WGC3Dclampf) |
| DELEGATE_TO_GL_1(blendEquation, BlendEquation, WGC3Denum) |
| @@ -868,7 +1221,7 @@ DELEGATE_TO_GL_4(bufferData, BufferData, |
| DELEGATE_TO_GL_4(bufferSubData, BufferSubData, |
| WGC3Denum, WGC3Dintptr, WGC3Dsizeiptr, const void*) |
| -DELEGATE_TO_GL_1R(checkFramebufferStatus, CheckFramebufferStatusEXT, |
| +DELEGATE_TO_GL_1R(checkFramebufferStatus, CheckFramebufferStatus, |
| WGC3Denum, WGC3Denum) |
| DELEGATE_TO_GL_1(clear, Clear, WGC3Dbitfield) |
| @@ -876,79 +1229,22 @@ DELEGATE_TO_GL_1(clear, Clear, WGC3Dbitfield) |
| DELEGATE_TO_GL_4(clearColor, ClearColor, |
| WGC3Dclampf, WGC3Dclampf, WGC3Dclampf, WGC3Dclampf) |
| -DELEGATE_TO_GL_1(clearDepth, ClearDepth, WGC3Dclampf) |
| +DELEGATE_TO_GL_1(clearDepth, ClearDepthf, WGC3Dclampf) |
| DELEGATE_TO_GL_1(clearStencil, ClearStencil, WGC3Dint) |
| DELEGATE_TO_GL_4(colorMask, ColorMask, |
| WGC3Dboolean, WGC3Dboolean, WGC3Dboolean, WGC3Dboolean) |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::compileShader(WebGLId shader) { |
| - makeContextCurrent(); |
| - |
| - ShaderSourceMap::iterator result = shader_source_map_.find(shader); |
| - if (result == shader_source_map_.end()) { |
| - // Passing down to gl driver to generate the correct error; or the case |
| - // where the shader deletion is delayed when it's attached to a program. |
| - glCompileShader(shader); |
| - return; |
| - } |
| - ShaderSourceEntry* entry = result->second; |
| - DCHECK(entry); |
| - |
| - if (!AngleValidateShaderSource(entry)) { |
| - // Shader didn't validate; don't move forward with compiling |
| - // translated source. |
| - return; |
| - } |
| - |
| - const char* translated_source = entry->translated_source.get(); |
| - int shader_length = translated_source ? strlen(translated_source) : 0; |
| - glShaderSource( |
| - shader, 1, const_cast<const char**>(&translated_source), &shader_length); |
| - glCompileShader(shader); |
| - |
| -#ifndef NDEBUG |
| - int compileStatus; |
| - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus); |
| - // DCHECK that ANGLE generated GLSL will be accepted by OpenGL |
| - DCHECK(compileStatus == GL_TRUE); |
| -#endif |
| -} |
| - |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::copyTexImage2D( |
| - WGC3Denum target, WGC3Dint level, WGC3Denum internalformat, WGC3Dint x, |
| - WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height, WGC3Dint border) { |
| - makeContextCurrent(); |
| - |
| - bool needsResolve = (attributes_.antialias && bound_fbo_ == multisample_fbo_); |
| - if (needsResolve) { |
| - ResolveMultisampledFramebuffer(x, y, width, height); |
| - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); |
| - } |
| +DELEGATE_TO_GL_1(compileShader, CompileShader, WebGLId) |
| - glCopyTexImage2D(target, level, internalformat, x, y, width, height, border); |
| - |
| - if (needsResolve) |
| - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); |
| -} |
| - |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::copyTexSubImage2D( |
| - WGC3Denum target, WGC3Dint level, WGC3Dint xoffset, WGC3Dint yoffset, |
| - WGC3Dint x, WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height) { |
| - makeContextCurrent(); |
| - |
| - bool needsResolve = (attributes_.antialias && bound_fbo_ == multisample_fbo_); |
| - if (needsResolve) { |
| - ResolveMultisampledFramebuffer(x, y, width, height); |
| - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); |
| - } |
| +DELEGATE_TO_GL_8(copyTexImage2D, CopyTexImage2D, |
| + WGC3Denum, WGC3Dint, WGC3Denum, WGC3Dint, WGC3Dint, |
| + WGC3Dsizei, WGC3Dsizei, WGC3Dint) |
| - glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); |
| - |
| - if (needsResolve) |
| - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); |
| -} |
| +DELEGATE_TO_GL_8(copyTexSubImage2D, CopyTexSubImage2D, |
| + WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, |
| + WGC3Dsizei, WGC3Dsizei) |
| DELEGATE_TO_GL_1(cullFace, CullFace, WGC3Denum) |
| @@ -956,69 +1252,73 @@ DELEGATE_TO_GL_1(depthFunc, DepthFunc, WGC3Denum) |
| DELEGATE_TO_GL_1(depthMask, DepthMask, WGC3Dboolean) |
| -DELEGATE_TO_GL_2(depthRange, DepthRange, WGC3Dclampf, WGC3Dclampf) |
| +DELEGATE_TO_GL_2(depthRange, DepthRangef, WGC3Dclampf, WGC3Dclampf) |
| DELEGATE_TO_GL_2(detachShader, DetachShader, WebGLId, WebGLId) |
| DELEGATE_TO_GL_1(disable, Disable, WGC3Denum) |
| -DELEGATE_TO_GL_1(disableVertexAttribArray, DisableVertexAttribArray, WGC3Duint) |
| +DELEGATE_TO_GL_1(disableVertexAttribArray, DisableVertexAttribArray, |
| + WGC3Duint) |
| DELEGATE_TO_GL_3(drawArrays, DrawArrays, WGC3Denum, WGC3Dint, WGC3Dsizei) |
| void WebGraphicsContext3DInProcessCommandBufferImpl::drawElements( |
| - WGC3Denum mode, WGC3Dsizei count, WGC3Denum type, WGC3Dintptr offset) { |
| - makeContextCurrent(); |
| - glDrawElements(mode, count, type, |
| - reinterpret_cast<void*>(static_cast<intptr_t>(offset))); |
| + WGC3Denum mode, |
| + WGC3Dsizei count, |
| + WGC3Denum type, |
| + WGC3Dintptr offset) { |
| + ClearContext(); |
| + gl_->DrawElements( |
| + mode, count, type, |
| + reinterpret_cast<void*>(static_cast<intptr_t>(offset))); |
| } |
| DELEGATE_TO_GL_1(enable, Enable, WGC3Denum) |
| -DELEGATE_TO_GL_1(enableVertexAttribArray, EnableVertexAttribArray, WGC3Duint) |
| +DELEGATE_TO_GL_1(enableVertexAttribArray, EnableVertexAttribArray, |
| + WGC3Duint) |
| DELEGATE_TO_GL(finish, Finish) |
| DELEGATE_TO_GL(flush, Flush) |
| -DELEGATE_TO_GL_4(framebufferRenderbuffer, FramebufferRenderbufferEXT, |
| +DELEGATE_TO_GL_4(framebufferRenderbuffer, FramebufferRenderbuffer, |
| WGC3Denum, WGC3Denum, WGC3Denum, WebGLId) |
| -DELEGATE_TO_GL_5(framebufferTexture2D, FramebufferTexture2DEXT, |
| +DELEGATE_TO_GL_5(framebufferTexture2D, FramebufferTexture2D, |
| WGC3Denum, WGC3Denum, WGC3Denum, WebGLId, WGC3Dint) |
| DELEGATE_TO_GL_1(frontFace, FrontFace, WGC3Denum) |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::generateMipmap(WGC3Denum target) { |
| - makeContextCurrent(); |
| - if (is_gles2_ || have_ext_framebuffer_object_) |
| - glGenerateMipmapEXT(target); |
| - // FIXME: provide alternative code path? This will be unpleasant |
| - // to implement if glGenerateMipmapEXT is not available -- it will |
| - // require a texture readback and re-upload. |
| -} |
| +DELEGATE_TO_GL_1(generateMipmap, GenerateMipmap, WGC3Denum) |
| bool WebGraphicsContext3DInProcessCommandBufferImpl::getActiveAttrib( |
| WebGLId program, WGC3Duint index, ActiveInfo& info) { |
| - makeContextCurrent(); |
| + ClearContext(); |
| if (!program) { |
| synthesizeGLError(GL_INVALID_VALUE); |
| return false; |
| } |
| GLint max_name_length = -1; |
| - glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_name_length); |
| + gl_->GetProgramiv( |
| + program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_name_length); |
| if (max_name_length < 0) |
| return false; |
| scoped_array<GLchar> name(new GLchar[max_name_length]); |
| + if (!name.get()) { |
| + synthesizeGLError(GL_OUT_OF_MEMORY); |
| + return false; |
| + } |
| GLsizei length = 0; |
| GLint size = -1; |
| GLenum type = 0; |
| - glGetActiveAttrib(program, index, max_name_length, |
| - &length, &size, &type, name.get()); |
| + gl_->GetActiveAttrib( |
| + program, index, max_name_length, &length, &size, &type, name.get()); |
| if (size < 0) { |
| return false; |
| } |
| - info.name = WebString::fromUTF8(name.get(), length); |
| + info.name = WebKit::WebString::fromUTF8(name.get(), length); |
| info.type = type; |
| info.size = size; |
| return true; |
| @@ -1026,21 +1326,26 @@ bool WebGraphicsContext3DInProcessCommandBufferImpl::getActiveAttrib( |
| bool WebGraphicsContext3DInProcessCommandBufferImpl::getActiveUniform( |
| WebGLId program, WGC3Duint index, ActiveInfo& info) { |
| - makeContextCurrent(); |
| + ClearContext(); |
| GLint max_name_length = -1; |
| - glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_name_length); |
| + gl_->GetProgramiv( |
| + program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_name_length); |
| if (max_name_length < 0) |
| return false; |
| scoped_array<GLchar> name(new GLchar[max_name_length]); |
| + if (!name.get()) { |
| + synthesizeGLError(GL_OUT_OF_MEMORY); |
| + return false; |
| + } |
| GLsizei length = 0; |
| GLint size = -1; |
| GLenum type = 0; |
| - glGetActiveUniform(program, index, max_name_length, |
| - &length, &size, &type, name.get()); |
| + gl_->GetActiveUniform( |
| + program, index, max_name_length, &length, &size, &type, name.get()); |
| if (size < 0) { |
| return false; |
| } |
| - info.name = WebString::fromUTF8(name.get(), length); |
| + info.name = WebKit::WebString::fromUTF8(name.get(), length); |
| info.type = type; |
| info.size = size; |
| return true; |
| @@ -1052,195 +1357,109 @@ DELEGATE_TO_GL_4(getAttachedShaders, GetAttachedShaders, |
| DELEGATE_TO_GL_2R(getAttribLocation, GetAttribLocation, |
| WebGLId, const WGC3Dchar*, WGC3Dint) |
| -DELEGATE_TO_GL_2(getBooleanv, GetBooleanv, |
| - WGC3Denum, WGC3Dboolean*) |
| +DELEGATE_TO_GL_2(getBooleanv, GetBooleanv, WGC3Denum, WGC3Dboolean*) |
| DELEGATE_TO_GL_3(getBufferParameteriv, GetBufferParameteriv, |
| WGC3Denum, WGC3Denum, WGC3Dint*) |
| -WebGraphicsContext3D::Attributes WebGraphicsContext3DInProcessCommandBufferImpl:: |
| - getContextAttributes() { |
| +WebKit::WebGraphicsContext3D::Attributes |
| +WebGraphicsContext3DInProcessCommandBufferImpl::getContextAttributes() { |
| return attributes_; |
| } |
| WGC3Denum WebGraphicsContext3DInProcessCommandBufferImpl::getError() { |
| - DCHECK(synthetic_errors_list_.size() == synthetic_errors_set_.size()); |
| - if (!synthetic_errors_set_.empty()) { |
| - WGC3Denum error = synthetic_errors_list_.front(); |
| - synthetic_errors_list_.pop_front(); |
| - synthetic_errors_set_.erase(error); |
| - return error; |
| + ClearContext(); |
| + if (!synthetic_errors_.empty()) { |
| + std::vector<WGC3Denum>::iterator iter = synthetic_errors_.begin(); |
| + WGC3Denum err = *iter; |
| + synthetic_errors_.erase(iter); |
| + return err; |
| } |
| - makeContextCurrent(); |
| - return glGetError(); |
| + return gl_->GetError(); |
| } |
| bool WebGraphicsContext3DInProcessCommandBufferImpl::isContextLost() { |
| - return false; |
| + return context_->IsCommandBufferContextLost(); |
| } |
| DELEGATE_TO_GL_2(getFloatv, GetFloatv, WGC3Denum, WGC3Dfloat*) |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::getFramebufferAttachmentParameteriv( |
| - WGC3Denum target, WGC3Denum attachment, |
| - WGC3Denum pname, WGC3Dint* value) { |
| - makeContextCurrent(); |
| - if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) |
| - attachment = GL_DEPTH_ATTACHMENT; // Or GL_STENCIL_ATTACHMENT; |
| - // either works. |
| - glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, value); |
| -} |
| +DELEGATE_TO_GL_4(getFramebufferAttachmentParameteriv, |
| + GetFramebufferAttachmentParameteriv, |
| + WGC3Denum, WGC3Denum, WGC3Denum, WGC3Dint*) |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::getIntegerv( |
| - WGC3Denum pname, WGC3Dint* value) { |
| - makeContextCurrent(); |
| - if (is_gles2_) { |
| - glGetIntegerv(pname, value); |
| - return; |
| - } |
| - // Need to emulate MAX_FRAGMENT/VERTEX_UNIFORM_VECTORS and |
| - // MAX_VARYING_VECTORS because desktop GL's corresponding queries |
| - // return the number of components whereas GLES2 return the number |
| - // of vectors (each vector has 4 components). Therefore, the value |
| - // returned by desktop GL needs to be divided by 4. |
| - switch (pname) { |
| - case MAX_FRAGMENT_UNIFORM_VECTORS: |
| - glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, value); |
| - *value /= 4; |
| - break; |
| - case MAX_VERTEX_UNIFORM_VECTORS: |
| - glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, value); |
| - *value /= 4; |
| - break; |
| - case MAX_VARYING_VECTORS: |
| - glGetIntegerv(GL_MAX_VARYING_FLOATS, value); |
| - *value /= 4; |
| - break; |
| - default: |
| - glGetIntegerv(pname, value); |
| - } |
| -} |
| +DELEGATE_TO_GL_2(getIntegerv, GetIntegerv, WGC3Denum, WGC3Dint*) |
| DELEGATE_TO_GL_3(getProgramiv, GetProgramiv, WebGLId, WGC3Denum, WGC3Dint*) |
| -WebString WebGraphicsContext3DInProcessCommandBufferImpl::getProgramInfoLog( |
| +WebKit::WebString WebGraphicsContext3DInProcessCommandBufferImpl::getProgramInfoLog( |
| WebGLId program) { |
| - makeContextCurrent(); |
| - GLint log_length; |
| - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length); |
| - if (!log_length) |
| - return WebString(); |
| - scoped_array<GLchar> log(new GLchar[log_length]); |
| - GLsizei returned_log_length; |
| - glGetProgramInfoLog(program, log_length, &returned_log_length, log.get()); |
| - DCHECK(log_length == returned_log_length + 1); |
| - WebString res = WebString::fromUTF8(log.get(), returned_log_length); |
| + ClearContext(); |
| + GLint logLength = 0; |
| + gl_->GetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength); |
| + if (!logLength) |
| + return WebKit::WebString(); |
| + scoped_array<GLchar> log(new GLchar[logLength]); |
| + if (!log.get()) |
| + return WebKit::WebString(); |
| + GLsizei returnedLogLength = 0; |
| + gl_->GetProgramInfoLog( |
| + program, logLength, &returnedLogLength, log.get()); |
| + DCHECK_EQ(logLength, returnedLogLength + 1); |
| + WebKit::WebString res = |
| + WebKit::WebString::fromUTF8(log.get(), returnedLogLength); |
| return res; |
| } |
| -DELEGATE_TO_GL_3(getRenderbufferParameteriv, GetRenderbufferParameterivEXT, |
| +DELEGATE_TO_GL_3(getRenderbufferParameteriv, GetRenderbufferParameteriv, |
| WGC3Denum, WGC3Denum, WGC3Dint*) |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::getShaderiv( |
| - WebGLId shader, WGC3Denum pname, WGC3Dint* value) { |
| - makeContextCurrent(); |
| - |
| - ShaderSourceMap::iterator result = shader_source_map_.find(shader); |
| - if (result != shader_source_map_.end()) { |
| - ShaderSourceEntry* entry = result->second; |
| - DCHECK(entry); |
| - switch (pname) { |
| - case GL_COMPILE_STATUS: |
| - if (!entry->is_valid) { |
| - *value = 0; |
| - return; |
| - } |
| - break; |
| - case GL_INFO_LOG_LENGTH: |
| - if (!entry->is_valid) { |
| - *value = entry->log.get() ? strlen(entry->log.get()) : 0; |
| - if (*value) |
| - (*value)++; |
| - return; |
| - } |
| - break; |
| - case GL_SHADER_SOURCE_LENGTH: |
| - *value = entry->source.get() ? strlen(entry->source.get()) : 0; |
| - if (*value) |
| - (*value)++; |
| - return; |
| - } |
| - } |
| - |
| - glGetShaderiv(shader, pname, value); |
| -} |
| - |
| -WebString WebGraphicsContext3DInProcessCommandBufferImpl::getShaderInfoLog(WebGLId shader) { |
| - makeContextCurrent(); |
| - |
| - ShaderSourceMap::iterator result = shader_source_map_.find(shader); |
| - if (result != shader_source_map_.end()) { |
| - ShaderSourceEntry* entry = result->second; |
| - DCHECK(entry); |
| - if (!entry->is_valid) { |
| - if (!entry->log.get()) |
| - return WebString(); |
| - WebString res = WebString::fromUTF8( |
| - entry->log.get(), strlen(entry->log.get())); |
| - return res; |
| - } |
| - } |
| - |
| - GLint log_length = 0; |
| - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length); |
| - if (log_length <= 1) |
| - return WebString(); |
| - scoped_array<GLchar> log(new GLchar[log_length]); |
| - GLsizei returned_log_length; |
| - glGetShaderInfoLog(shader, log_length, &returned_log_length, log.get()); |
| - DCHECK(log_length == returned_log_length + 1); |
| - WebString res = WebString::fromUTF8(log.get(), returned_log_length); |
| +DELEGATE_TO_GL_3(getShaderiv, GetShaderiv, WebGLId, WGC3Denum, WGC3Dint*) |
| + |
| +WebKit::WebString WebGraphicsContext3DInProcessCommandBufferImpl::getShaderInfoLog( |
| + WebGLId shader) { |
| + ClearContext(); |
| + GLint logLength = 0; |
| + gl_->GetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength); |
| + if (!logLength) |
| + return WebKit::WebString(); |
| + scoped_array<GLchar> log(new GLchar[logLength]); |
| + if (!log.get()) |
| + return WebKit::WebString(); |
| + GLsizei returnedLogLength = 0; |
| + gl_->GetShaderInfoLog( |
| + shader, logLength, &returnedLogLength, log.get()); |
| + DCHECK_EQ(logLength, returnedLogLength + 1); |
| + WebKit::WebString res = |
| + WebKit::WebString::fromUTF8(log.get(), returnedLogLength); |
| return res; |
| } |
| -WebString WebGraphicsContext3DInProcessCommandBufferImpl::getShaderSource(WebGLId shader) { |
| - makeContextCurrent(); |
| - |
| - ShaderSourceMap::iterator result = shader_source_map_.find(shader); |
| - if (result != shader_source_map_.end()) { |
| - ShaderSourceEntry* entry = result->second; |
| - DCHECK(entry); |
| - if (!entry->source.get()) |
| - return WebString(); |
| - WebString res = WebString::fromUTF8( |
| - entry->source.get(), strlen(entry->source.get())); |
| - return res; |
| - } |
| - |
| - GLint log_length = 0; |
| - glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &log_length); |
| - if (log_length <= 1) |
| - return WebString(); |
| - scoped_array<GLchar> log(new GLchar[log_length]); |
| - GLsizei returned_log_length; |
| - glGetShaderSource(shader, log_length, &returned_log_length, log.get()); |
| - DCHECK(log_length == returned_log_length + 1); |
| - WebString res = WebString::fromUTF8(log.get(), returned_log_length); |
| +WebKit::WebString WebGraphicsContext3DInProcessCommandBufferImpl::getShaderSource( |
| + WebGLId shader) { |
| + ClearContext(); |
| + GLint logLength = 0; |
| + gl_->GetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &logLength); |
| + if (!logLength) |
| + return WebKit::WebString(); |
| + scoped_array<GLchar> log(new GLchar[logLength]); |
| + if (!log.get()) |
| + return WebKit::WebString(); |
| + GLsizei returnedLogLength = 0; |
| + gl_->GetShaderSource( |
| + shader, logLength, &returnedLogLength, log.get()); |
| + DCHECK_EQ(logLength, returnedLogLength + 1); |
| + WebKit::WebString res = |
| + WebKit::WebString::fromUTF8(log.get(), returnedLogLength); |
| return res; |
| } |
| -WebString WebGraphicsContext3DInProcessCommandBufferImpl::getString(WGC3Denum name) { |
| - makeContextCurrent(); |
| - std::string result(reinterpret_cast<const char*>(glGetString(name))); |
| - if (name == GL_EXTENSIONS) { |
| - // GL_CHROMIUM_copy_texture_to_parent_texture requires the |
| - // desktopGL-only function glGetTexLevelParameteriv (GLES2 |
| - // doesn't support it). |
| - if (!is_gles2_) |
| - result += " GL_CHROMIUM_copy_texture_to_parent_texture"; |
| - } |
| - return WebString::fromUTF8(result.c_str()); |
| +WebKit::WebString WebGraphicsContext3DInProcessCommandBufferImpl::getString( |
| + WGC3Denum name) { |
| + ClearContext(); |
| + return WebKit::WebString::fromUTF8( |
| + reinterpret_cast<const char*>(gl_->GetString(name))); |
| } |
| DELEGATE_TO_GL_3(getTexParameterfv, GetTexParameterfv, |
| @@ -1264,10 +1483,12 @@ DELEGATE_TO_GL_3(getVertexAttribiv, GetVertexAttribiv, |
| WGC3Dsizeiptr WebGraphicsContext3DInProcessCommandBufferImpl::getVertexAttribOffset( |
| WGC3Duint index, WGC3Denum pname) { |
| - makeContextCurrent(); |
| - void* pointer; |
| - glGetVertexAttribPointerv(index, pname, &pointer); |
| - return static_cast<WGC3Dsizeiptr>(reinterpret_cast<intptr_t>(pointer)); |
| + ClearContext(); |
| + GLvoid* value = NULL; |
| + // NOTE: If pname is ever a value that returns more then 1 element |
| + // this will corrupt memory. |
| + gl_->GetVertexAttribPointerv(index, pname, &value); |
| + return static_cast<WGC3Dsizeiptr>(reinterpret_cast<intptr_t>(value)); |
| } |
| DELEGATE_TO_GL_2(hint, Hint, WGC3Denum, WGC3Denum) |
| @@ -1276,11 +1497,11 @@ DELEGATE_TO_GL_1RB(isBuffer, IsBuffer, WebGLId, WGC3Dboolean) |
| DELEGATE_TO_GL_1RB(isEnabled, IsEnabled, WGC3Denum, WGC3Dboolean) |
| -DELEGATE_TO_GL_1RB(isFramebuffer, IsFramebufferEXT, WebGLId, WGC3Dboolean) |
| +DELEGATE_TO_GL_1RB(isFramebuffer, IsFramebuffer, WebGLId, WGC3Dboolean) |
| DELEGATE_TO_GL_1RB(isProgram, IsProgram, WebGLId, WGC3Dboolean) |
| -DELEGATE_TO_GL_1RB(isRenderbuffer, IsRenderbufferEXT, WebGLId, WGC3Dboolean) |
| +DELEGATE_TO_GL_1RB(isRenderbuffer, IsRenderbuffer, WebGLId, WGC3Dboolean) |
| DELEGATE_TO_GL_1RB(isShader, IsShader, WebGLId, WGC3Dboolean) |
| @@ -1294,86 +1515,26 @@ DELEGATE_TO_GL_2(pixelStorei, PixelStorei, WGC3Denum, WGC3Dint) |
| DELEGATE_TO_GL_2(polygonOffset, PolygonOffset, WGC3Dfloat, WGC3Dfloat) |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::readPixels( |
| - WGC3Dint x, WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height, |
| - WGC3Denum format, WGC3Denum type, void* pixels) { |
| - makeContextCurrent(); |
| - // FIXME: remove the two glFlush calls when the driver bug is fixed, i.e., |
| - // all previous rendering calls should be done before reading pixels. |
| - glFlush(); |
| - bool needs_resolve = |
| - (attributes_.antialias && bound_fbo_ == multisample_fbo_); |
| - if (needs_resolve) { |
| - ResolveMultisampledFramebuffer(x, y, width, height); |
| - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); |
| - glFlush(); |
| - } |
| - |
| - glReadPixels(x, y, width, height, format, type, pixels); |
| - |
| - if (needs_resolve) |
| - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); |
| -} |
| +DELEGATE_TO_GL_7(readPixels, ReadPixels, |
| + WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei, WGC3Denum, |
| + WGC3Denum, void*) |
| void WebGraphicsContext3DInProcessCommandBufferImpl::releaseShaderCompiler() { |
| + ClearContext(); |
| } |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::renderbufferStorage( |
| - WGC3Denum target, |
| - WGC3Denum internalformat, |
| - WGC3Dsizei width, |
| - WGC3Dsizei height) { |
| - makeContextCurrent(); |
| - if (!is_gles2_) { |
| - switch (internalformat) { |
| - case GL_DEPTH_STENCIL: |
| - internalformat = GL_DEPTH24_STENCIL8_EXT; |
| - break; |
| - case GL_DEPTH_COMPONENT16: |
| - internalformat = GL_DEPTH_COMPONENT; |
| - break; |
| - case GL_RGBA4: |
| - case GL_RGB5_A1: |
| - internalformat = GL_RGBA; |
| - break; |
| - case 0x8D62: // GL_RGB565 |
| - internalformat = GL_RGB; |
| - break; |
| - } |
| - } |
| - glRenderbufferStorageEXT(target, internalformat, width, height); |
| -} |
| +DELEGATE_TO_GL_4(renderbufferStorage, RenderbufferStorage, |
| + WGC3Denum, WGC3Denum, WGC3Dsizei, WGC3Dsizei) |
| -DELEGATE_TO_GL_2(sampleCoverage, SampleCoverage, WGC3Dclampf, WGC3Dboolean) |
| +DELEGATE_TO_GL_2(sampleCoverage, SampleCoverage, WGC3Dfloat, WGC3Dboolean) |
| DELEGATE_TO_GL_4(scissor, Scissor, WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei) |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::texImage2D( |
| - WGC3Denum target, WGC3Dint level, WGC3Denum internalFormat, |
| - WGC3Dsizei width, WGC3Dsizei height, WGC3Dint border, |
| - WGC3Denum format, WGC3Denum type, const void* pixels) { |
| - if (width && height && !pixels) { |
| - synthesizeGLError(GL_INVALID_VALUE); |
| - return; |
| - } |
| - makeContextCurrent(); |
| - glTexImage2D(target, level, internalFormat, |
| - width, height, border, format, type, pixels); |
| -} |
| - |
| void WebGraphicsContext3DInProcessCommandBufferImpl::shaderSource( |
| - WebGLId shader, const WGC3Dchar* source) { |
| - makeContextCurrent(); |
| - GLint length = source ? strlen(source) : 0; |
| - ShaderSourceMap::iterator result = shader_source_map_.find(shader); |
| - if (result != shader_source_map_.end()) { |
| - ShaderSourceEntry* entry = result->second; |
| - DCHECK(entry); |
| - entry->source.reset(new char[length + 1]); |
| - memcpy(entry->source.get(), source, (length + 1) * sizeof(char)); |
| - } else { |
| - glShaderSource(shader, 1, &source, &length); |
| - } |
| + WebGLId shader, const WGC3Dchar* string) { |
| + ClearContext(); |
| + GLint length = strlen(string); |
| + gl_->ShaderSource(shader, 1, &string, &length); |
| } |
| DELEGATE_TO_GL_3(stencilFunc, StencilFunc, WGC3Denum, WGC3Dint, WGC3Duint) |
| @@ -1392,9 +1553,27 @@ DELEGATE_TO_GL_3(stencilOp, StencilOp, |
| DELEGATE_TO_GL_4(stencilOpSeparate, StencilOpSeparate, |
| WGC3Denum, WGC3Denum, WGC3Denum, WGC3Denum) |
| -DELEGATE_TO_GL_3(texParameterf, TexParameterf, WGC3Denum, WGC3Denum, WGC3Dfloat) |
| +DELEGATE_TO_GL_9(texImage2D, TexImage2D, |
| + WGC3Denum, WGC3Dint, WGC3Denum, WGC3Dsizei, WGC3Dsizei, |
| + WGC3Dint, WGC3Denum, WGC3Denum, const void*) |
| + |
| +DELEGATE_TO_GL_3(texParameterf, TexParameterf, |
| + WGC3Denum, WGC3Denum, WGC3Dfloat); |
| + |
| +static const unsigned int kTextureWrapR = 0x8072; |
| -DELEGATE_TO_GL_3(texParameteri, TexParameteri, WGC3Denum, WGC3Denum, WGC3Dint) |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::texParameteri( |
| + WGC3Denum target, WGC3Denum pname, WGC3Dint param) { |
| + ClearContext(); |
| + // TODO(kbr): figure out whether the setting of TEXTURE_WRAP_R in |
| + // GraphicsContext3D.cpp is strictly necessary to avoid seams at the |
| + // edge of cube maps, and, if it is, push it into the GLES2 service |
| + // side code. |
| + if (pname == kTextureWrapR) { |
| + return; |
| + } |
| + gl_->TexParameteri(target, pname, param); |
| +} |
| DELEGATE_TO_GL_9(texSubImage2D, TexSubImage2D, |
| WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dsizei, |
| @@ -1402,8 +1581,8 @@ DELEGATE_TO_GL_9(texSubImage2D, TexSubImage2D, |
| DELEGATE_TO_GL_2(uniform1f, Uniform1f, WGC3Dint, WGC3Dfloat) |
| -DELEGATE_TO_GL_3(uniform1fv, Uniform1fv, |
| - WGC3Dint, WGC3Dsizei, const WGC3Dfloat*) |
| +DELEGATE_TO_GL_3(uniform1fv, Uniform1fv, WGC3Dint, WGC3Dsizei, |
| + const WGC3Dfloat*) |
| DELEGATE_TO_GL_2(uniform1i, Uniform1i, WGC3Dint, WGC3Dint) |
| @@ -1411,18 +1590,18 @@ DELEGATE_TO_GL_3(uniform1iv, Uniform1iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) |
| DELEGATE_TO_GL_3(uniform2f, Uniform2f, WGC3Dint, WGC3Dfloat, WGC3Dfloat) |
| -DELEGATE_TO_GL_3(uniform2fv, Uniform2fv, |
| - WGC3Dint, WGC3Dsizei, const WGC3Dfloat*) |
| +DELEGATE_TO_GL_3(uniform2fv, Uniform2fv, WGC3Dint, WGC3Dsizei, |
| + const WGC3Dfloat*) |
| DELEGATE_TO_GL_3(uniform2i, Uniform2i, WGC3Dint, WGC3Dint, WGC3Dint) |
| DELEGATE_TO_GL_3(uniform2iv, Uniform2iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) |
| -DELEGATE_TO_GL_4(uniform3f, Uniform3f, |
| - WGC3Dint, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) |
| +DELEGATE_TO_GL_4(uniform3f, Uniform3f, WGC3Dint, |
| + WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) |
| -DELEGATE_TO_GL_3(uniform3fv, Uniform3fv, |
| - WGC3Dint, WGC3Dsizei, const WGC3Dfloat*) |
| +DELEGATE_TO_GL_3(uniform3fv, Uniform3fv, WGC3Dint, WGC3Dsizei, |
| + const WGC3Dfloat*) |
| DELEGATE_TO_GL_4(uniform3i, Uniform3i, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint) |
| @@ -1431,8 +1610,8 @@ DELEGATE_TO_GL_3(uniform3iv, Uniform3iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) |
| DELEGATE_TO_GL_5(uniform4f, Uniform4f, WGC3Dint, |
| WGC3Dfloat, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) |
| -DELEGATE_TO_GL_3(uniform4fv, Uniform4fv, |
| - WGC3Dint, WGC3Dsizei, const WGC3Dfloat*) |
| +DELEGATE_TO_GL_3(uniform4fv, Uniform4fv, WGC3Dint, WGC3Dsizei, |
| + const WGC3Dfloat*) |
| DELEGATE_TO_GL_5(uniform4i, Uniform4i, WGC3Dint, |
| WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint) |
| @@ -1454,209 +1633,134 @@ DELEGATE_TO_GL_1(validateProgram, ValidateProgram, WebGLId) |
| DELEGATE_TO_GL_2(vertexAttrib1f, VertexAttrib1f, WGC3Duint, WGC3Dfloat) |
| -DELEGATE_TO_GL_2(vertexAttrib1fv, VertexAttrib1fv, WGC3Duint, const WGC3Dfloat*) |
| +DELEGATE_TO_GL_2(vertexAttrib1fv, VertexAttrib1fv, WGC3Duint, |
| + const WGC3Dfloat*) |
| -DELEGATE_TO_GL_3(vertexAttrib2f, VertexAttrib2f, |
| - WGC3Duint, WGC3Dfloat, WGC3Dfloat) |
| +DELEGATE_TO_GL_3(vertexAttrib2f, VertexAttrib2f, WGC3Duint, |
| + WGC3Dfloat, WGC3Dfloat) |
| -DELEGATE_TO_GL_2(vertexAttrib2fv, VertexAttrib2fv, WGC3Duint, const WGC3Dfloat*) |
| +DELEGATE_TO_GL_2(vertexAttrib2fv, VertexAttrib2fv, WGC3Duint, |
| + const WGC3Dfloat*) |
| -DELEGATE_TO_GL_4(vertexAttrib3f, VertexAttrib3f, |
| - WGC3Duint, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) |
| +DELEGATE_TO_GL_4(vertexAttrib3f, VertexAttrib3f, WGC3Duint, |
| + WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) |
| -DELEGATE_TO_GL_2(vertexAttrib3fv, VertexAttrib3fv, WGC3Duint, const WGC3Dfloat*) |
| +DELEGATE_TO_GL_2(vertexAttrib3fv, VertexAttrib3fv, WGC3Duint, |
| + const WGC3Dfloat*) |
| -DELEGATE_TO_GL_5(vertexAttrib4f, VertexAttrib4f, |
| - WGC3Duint, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) |
| +DELEGATE_TO_GL_5(vertexAttrib4f, VertexAttrib4f, WGC3Duint, |
| + WGC3Dfloat, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) |
| -DELEGATE_TO_GL_2(vertexAttrib4fv, VertexAttrib4fv, WGC3Duint, const WGC3Dfloat*) |
| +DELEGATE_TO_GL_2(vertexAttrib4fv, VertexAttrib4fv, WGC3Duint, |
| + const WGC3Dfloat*) |
| void WebGraphicsContext3DInProcessCommandBufferImpl::vertexAttribPointer( |
| WGC3Duint index, WGC3Dint size, WGC3Denum type, WGC3Dboolean normalized, |
| WGC3Dsizei stride, WGC3Dintptr offset) { |
| - makeContextCurrent(); |
| - glVertexAttribPointer(index, size, type, normalized, stride, |
| - reinterpret_cast<void*>(static_cast<intptr_t>(offset))); |
| + ClearContext(); |
| + gl_->VertexAttribPointer( |
| + index, size, type, normalized, stride, |
| + reinterpret_cast<void*>(static_cast<intptr_t>(offset))); |
| } |
| -DELEGATE_TO_GL_4(viewport, Viewport, WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei) |
| +DELEGATE_TO_GL_4(viewport, Viewport, |
| + WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei) |
| WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createBuffer() { |
| - makeContextCurrent(); |
| + ClearContext(); |
| GLuint o; |
| - glGenBuffersARB(1, &o); |
| + gl_->GenBuffers(1, &o); |
| return o; |
| } |
| WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createFramebuffer() { |
| - makeContextCurrent(); |
| + ClearContext(); |
| GLuint o = 0; |
| - glGenFramebuffersEXT(1, &o); |
| + gl_->GenFramebuffers(1, &o); |
| return o; |
| } |
| WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createProgram() { |
| - makeContextCurrent(); |
| - return glCreateProgram(); |
| + ClearContext(); |
| + return gl_->CreateProgram(); |
| } |
| WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createRenderbuffer() { |
| - makeContextCurrent(); |
| + ClearContext(); |
| GLuint o; |
| - glGenRenderbuffersEXT(1, &o); |
| + gl_->GenRenderbuffers(1, &o); |
| return o; |
| } |
| -WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createShader( |
| - WGC3Denum shaderType) { |
| - makeContextCurrent(); |
| - DCHECK(shaderType == GL_VERTEX_SHADER || shaderType == GL_FRAGMENT_SHADER); |
| - GLuint shader = glCreateShader(shaderType); |
| - if (shader) { |
| - ShaderSourceMap::iterator result = shader_source_map_.find(shader); |
| - if (result != shader_source_map_.end()) { |
| - delete result->second; |
| - shader_source_map_.erase(result); |
| - } |
| - shader_source_map_.insert( |
| - ShaderSourceMap::value_type(shader, new ShaderSourceEntry(shaderType))); |
| - } |
| - |
| - return shader; |
| -} |
| +DELEGATE_TO_GL_1R(createShader, CreateShader, WGC3Denum, WebGLId); |
| WebGLId WebGraphicsContext3DInProcessCommandBufferImpl::createTexture() { |
| - makeContextCurrent(); |
| + ClearContext(); |
| GLuint o; |
| - glGenTextures(1, &o); |
| + gl_->GenTextures(1, &o); |
| return o; |
| } |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::deleteBuffer(WebGLId buffer) { |
| - makeContextCurrent(); |
| - glDeleteBuffersARB(1, &buffer); |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::deleteBuffer( |
| + WebGLId buffer) { |
| + ClearContext(); |
| + gl_->DeleteBuffers(1, &buffer); |
| } |
| void WebGraphicsContext3DInProcessCommandBufferImpl::deleteFramebuffer( |
| WebGLId framebuffer) { |
| - makeContextCurrent(); |
| - glDeleteFramebuffersEXT(1, &framebuffer); |
| + ClearContext(); |
| + gl_->DeleteFramebuffers(1, &framebuffer); |
| } |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::deleteProgram(WebGLId program) { |
| - makeContextCurrent(); |
| - glDeleteProgram(program); |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::deleteProgram( |
| + WebGLId program) { |
| + ClearContext(); |
| + gl_->DeleteProgram(program); |
| } |
| void WebGraphicsContext3DInProcessCommandBufferImpl::deleteRenderbuffer( |
| WebGLId renderbuffer) { |
| - makeContextCurrent(); |
| - glDeleteRenderbuffersEXT(1, &renderbuffer); |
| + ClearContext(); |
| + gl_->DeleteRenderbuffers(1, &renderbuffer); |
| } |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::deleteShader(WebGLId shader) { |
| - makeContextCurrent(); |
| - |
| - ShaderSourceMap::iterator result = shader_source_map_.find(shader); |
| - if (result != shader_source_map_.end()) { |
| - delete result->second; |
| - shader_source_map_.erase(result); |
| - } |
| - glDeleteShader(shader); |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::deleteShader( |
| + WebGLId shader) { |
| + ClearContext(); |
| + gl_->DeleteShader(shader); |
| } |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::deleteTexture(WebGLId texture) { |
| - makeContextCurrent(); |
| - glDeleteTextures(1, &texture); |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::deleteTexture( |
| + WebGLId texture) { |
| + ClearContext(); |
| + gl_->DeleteTextures(1, &texture); |
| } |
| -bool WebGraphicsContext3DInProcessCommandBufferImpl::AngleCreateCompilers() { |
| - if (!ShInitialize()) |
| - return false; |
| - |
| - ShBuiltInResources resources; |
| - ShInitBuiltInResources(&resources); |
| - getIntegerv(GL_MAX_VERTEX_ATTRIBS, &resources.MaxVertexAttribs); |
| - getIntegerv(MAX_VERTEX_UNIFORM_VECTORS, &resources.MaxVertexUniformVectors); |
| - getIntegerv(MAX_VARYING_VECTORS, &resources.MaxVaryingVectors); |
| - getIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, |
| - &resources.MaxVertexTextureImageUnits); |
| - getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, |
| - &resources.MaxCombinedTextureImageUnits); |
| - getIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &resources.MaxTextureImageUnits); |
| - getIntegerv(MAX_FRAGMENT_UNIFORM_VECTORS, |
| - &resources.MaxFragmentUniformVectors); |
| - // Always set to 1 for OpenGL ES. |
| - resources.MaxDrawBuffers = 1; |
| - |
| - fragment_compiler_ = ShConstructCompiler( |
| - SH_FRAGMENT_SHADER, SH_WEBGL_SPEC, &resources); |
| - vertex_compiler_ = ShConstructCompiler( |
| - SH_VERTEX_SHADER, SH_WEBGL_SPEC, &resources); |
| - return (fragment_compiler_ && vertex_compiler_); |
| -} |
| - |
| -void WebGraphicsContext3DInProcessCommandBufferImpl::AngleDestroyCompilers() { |
| - if (fragment_compiler_) { |
| - ShDestruct(fragment_compiler_); |
| - fragment_compiler_ = 0; |
| - } |
| - if (vertex_compiler_) { |
| - ShDestruct(vertex_compiler_); |
| - vertex_compiler_ = 0; |
| - } |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::copyTextureToCompositor( |
| + WebGLId texture, WebGLId parentTexture) { |
| + ClearContext(); |
| + gl_->CopyTextureToParentTextureCHROMIUM(texture, parentTexture); |
| + gl_->Flush(); |
| } |
| -bool WebGraphicsContext3DInProcessCommandBufferImpl::AngleValidateShaderSource( |
| - ShaderSourceEntry* entry) { |
| - entry->is_valid = false; |
| - entry->translated_source.reset(); |
| - entry->log.reset(); |
| - |
| - ShHandle compiler = 0; |
| - switch (entry->type) { |
| - case GL_FRAGMENT_SHADER: |
| - compiler = fragment_compiler_; |
| - break; |
| - case GL_VERTEX_SHADER: |
| - compiler = vertex_compiler_; |
| - break; |
| - } |
| - if (!compiler) |
| - return false; |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::OnSwapBuffersComplete() { |
| +} |
| - char* source = entry->source.get(); |
| - if (!ShCompile(compiler, &source, 1, SH_OBJECT_CODE)) { |
| - int logSize = 0; |
| - ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &logSize); |
| - if (logSize > 1) { |
| - entry->log.reset(new char[logSize]); |
| - ShGetInfoLog(compiler, entry->log.get()); |
| - } |
| - return false; |
| - } |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::setContextLostCallback( |
| + WebGraphicsContext3D::WebGraphicsContextLostCallback* cb) |
| +{ |
| + context_lost_callback_ = cb; |
| +} |
| - int length = 0; |
| - if (is_gles2_) { |
| - // ANGLE does not yet have a GLSL ES backend. Therefore if the |
| - // compile succeeds we send the original source down. |
| - length = strlen(entry->source.get()); |
| - if (length > 0) |
| - ++length; // Add null terminator |
| - } else { |
| - ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &length); |
| - } |
| - if (length > 1) { |
| - entry->translated_source.reset(new char[length]); |
| - if (is_gles2_) |
| - strncpy(entry->translated_source.get(), entry->source.get(), length); |
| - else |
| - ShGetObjectCode(compiler, entry->translated_source.get()); |
| +void WebGraphicsContext3DInProcessCommandBufferImpl::OnContextLost() { |
| + if (context_lost_callback_) { |
| + context_lost_callback_->onContextLost(); |
| } |
| - entry->is_valid = true; |
| - return true; |
| } |
| } // namespace gpu |
| } // namespace webkit |
| +#endif // defined(ENABLE_GPU) |
| + |