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 dfb49597f1dd0a32ad963313fd971db6eea6477d..db6010feb34128c469032e9578555e5eefec3ab5 100644 |
--- a/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc |
+++ b/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc |
@@ -2,574 +2,912 @@ |
// 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/scoped_ptr.h" |
+#include "base/memory/singleton.h" |
+#include "base/metrics/histogram.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; |
+// Allocator for latches. |
+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_ = gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(1, 1)); |
+ private: |
+ friend struct DefaultSingletonTraits<LatchAllocator>; |
- if (!gl_surface_.get()) { |
- if (!is_gles2_) |
- return false; |
+ scoped_array<uint32> latches_; |
- // 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_ = gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(1, 1)); |
- if (!gl_surface_.get()) |
- return false; |
- } |
+ DISALLOW_COPY_AND_ASSIGN(LatchAllocator); |
+}; |
- gl_context_ = gfx::GLContext::CreateGLContext(share_context, |
- gl_surface_.get()); |
- if (!gl_context_.get()) { |
- if (!is_gles2_) |
- return false; |
+//////////////////////////////////////////////////////////////////////////////// |
+/// LatchAllocator implementation |
- // 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_ = gfx::GLContext::CreateGLContext(share_context, |
- gl_surface_.get()); |
- if (!gl_context_.get()) |
- return false; |
- } |
+LatchAllocator* LatchAllocator::GetInstance() { |
+ return Singleton<LatchAllocator>::get(); |
+} |
- 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_ = NULL; |
- return false; |
- } |
+LatchAllocator::LatchAllocator() { |
+ latches_.reset(new uint32[size()]); |
+ // Mark all latches as unallocated. |
+ for (uint32 i = 0; i < kMaxLatchesPerRenderer; ++i) |
+ latches_[i] = kFreeLatch; |
+} |
- 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() { |
+} |
+ |
+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; |
- // 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); |
+ gpu_scheduler_ = new GpuScheduler(command_buffer_.get(), NULL, NULL); |
+ |
+ 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)); |
+ |
+ // 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. |
+ transfer_buffer_id_ = |
+ command_buffer_->CreateTransferBuffer( |
+ kTransferBufferSize, ::gpu::kCommandBufferSharedMemoryId); |
+ if (transfer_buffer_id_ < 0) { |
+ Destroy(); |
+ return false; |
+ } |
+ |
+ // Map the buffer. |
+ Buffer transfer_buffer = |
+ command_buffer_->GetTransferBuffer(transfer_buffer_id_); |
+ if (!transfer_buffer.ptr) { |
+ Destroy(); |
+ return false; |
+ } |
- // FIXME: cleanup. |
- NOTIMPLEMENTED(); |
+ // 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; |
+ } |
+ if (parent_to_child_latch_ != kInvalidLatchId) { |
+ DestroyLatch(parent_to_child_latch_); |
+ parent_to_child_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 (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_; |
+ } |
} |
- 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(); |
+ |
+ fprintf(stderr, "Running command buffer\n"); |
+ |
+ return true; |
+} |
+ |
+bool WebGraphicsContext3DInProcessCommandBufferImpl::makeContextCurrent() { |
+ return GLInProcessContext::MakeCurrent(context_); |
+} |
+ |
+void WebGraphicsContext3DInProcessCommandBufferImpl::ClearContext() { |
+ // NOTE: Comment in the line below to check for code that is not calling |
+ // eglMakeCurrent where appropriate. The issue is code using |
+ // WebGraphicsContext3D does not need to call makeContextCurrent. Code using |
+ // direct OpenGL bindings needs to call the appropriate form of |
+ // eglMakeCurrent. If it doesn't it will be issuing commands on the wrong |
+ // context. Uncommenting the line below clears the current context so that |
+ // any code not calling eglMakeCurrent in the appropriate place should crash. |
+ // This is not a perfect test but generally code that used the direct OpenGL |
+ // bindings should not be mixed with code that uses WebGraphicsContext3D. |
+ // |
+ // GLInProcessContext::MakeCurrent(NULL); |
+} |
+ |
+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; |
+ |
+ // TODO(gmam): See if we can comment this in. |
+ // 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) { |
+ // TODO(gmam): See if we can comment this in. |
+ // ClearContext(); |
+ return context_->CreateParentTexture(gfx::Size(width, height)); |
+} |
+ |
+void WebGraphicsContext3DInProcessCommandBufferImpl::deleteCompositorTexture( |
+ WebGLId parent_texture) { |
+ // TODO(gmam): See if we can comment this in. |
+ // 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 +919,13 @@ 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) { |
+ // TODO(gmam): See if we can comment this in. |
+ // 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 +934,276 @@ 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; |
+void WebGraphicsContext3DInProcessCommandBufferImpl:: |
+ copyTextureToParentTextureCHROMIUM(WebGLId texture, WebGLId parentTexture) { |
+ // TODO(gmam): See if we can comment this in. |
+ // ClearContext(); |
+ copyTextureToCompositor(texture, parentTexture); |
+} |
- 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_); |
-} |
- |
-void WebGraphicsContext3DInProcessCommandBufferImpl::getParentToChildLatchCHROMIUM( |
- WGC3Duint* latch_id) |
+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) |
+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) |
{ |
+ // TODO(gmam): See if we can comment this in. |
+ // ClearContext(); |
+ gl_->WaitLatchCHROMIUM(latch_id); |
} |
void WebGraphicsContext3DInProcessCommandBufferImpl::setLatchCHROMIUM( |
WGC3Duint latch_id) |
{ |
+ // TODO(gmam): See if we can comment this in. |
+ // ClearContext(); |
+ gl_->SetLatchCHROMIUM(latch_id); |
+ // required to ensure set command is sent to GPU process |
+ gl_->Flush(); |
+} |
+ |
+void WebGraphicsContext3DInProcessCommandBufferImpl:: |
+ rateLimitOffscreenContextCHROMIUM() { |
+ // TODO(gmam): See if we can comment this in. |
+ // ClearContext(); |
+ gl_->RateLimitOffscreenContextCHROMIUM(); |
} |
-WebString WebGraphicsContext3DInProcessCommandBufferImpl:: |
+WebKit::WebString WebGraphicsContext3DInProcessCommandBufferImpl:: |
getRequestableExtensionsCHROMIUM() { |
- return WebString(); |
+ // TODO(gmam): See if we can comment this in. |
+ // ClearContext(); |
+ return WebKit::WebString::fromUTF8( |
+ gl_->GetRequestableExtensionsCHROMIUM()); |
} |
-void WebGraphicsContext3DInProcessCommandBufferImpl::requestExtensionCHROMIUM(const char*) { |
+void WebGraphicsContext3DInProcessCommandBufferImpl::requestExtensionCHROMIUM( |
+ const char* extension) { |
+ // TODO(gmam): See if we can comment this in. |
+ // 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_); |
- } |
- |
- 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(); |
+DELEGATE_TO_GL_1(compileShader, CompileShader, WebGLId) |
- bool needsResolve = (attributes_.antialias && bound_fbo_ == multisample_fbo_); |
- if (needsResolve) { |
- ResolveMultisampledFramebuffer(x, y, width, height); |
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); |
- } |
- |
- glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); |
+DELEGATE_TO_GL_8(copyTexImage2D, CopyTexImage2D, |
+ WGC3Denum, WGC3Dint, WGC3Denum, WGC3Dint, WGC3Dint, |
+ WGC3Dsizei, WGC3Dsizei, WGC3Dint) |
- 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( |
- 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); |
+WebKit::WebString WebGraphicsContext3DInProcessCommandBufferImpl:: |
+ getProgramInfoLog(WebGLId program) { |
+ 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, |
@@ -1262,12 +1481,14 @@ DELEGATE_TO_GL_3(getVertexAttribfv, GetVertexAttribfv, |
DELEGATE_TO_GL_3(getVertexAttribiv, GetVertexAttribiv, |
WGC3Duint, WGC3Denum, WGC3Dint*) |
-WGC3Dsizeiptr WebGraphicsContext3DInProcessCommandBufferImpl::getVertexAttribOffset( |
- WGC3Duint index, WGC3Denum pname) { |
- makeContextCurrent(); |
- void* pointer; |
- glGetVertexAttribPointerv(index, pname, &pointer); |
- return static_cast<WGC3Dsizeiptr>(reinterpret_cast<intptr_t>(pointer)); |
+WGC3Dsizeiptr WebGraphicsContext3DInProcessCommandBufferImpl:: |
+ getVertexAttribOffset(WGC3Duint index, WGC3Denum pname) { |
+ 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,135 @@ 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) { |
+ // TODO(gmam): See if we can comment this in. |
+ // 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) |
+ |