summaryrefslogtreecommitdiffstats
path: root/webkit/glue/plugins
diff options
context:
space:
mode:
authorKristian Monsen <kristianm@google.com>2010-10-27 15:07:08 +0100
committerKristian Monsen <kristianm@google.com>2010-10-27 15:07:08 +0100
commitb922201e41fa263ae6bc159713907e4a9b340ba8 (patch)
tree050986c20be782f5964f03d4a67d57fb9e35bf5a /webkit/glue/plugins
parent8ae428e0fb7feea16d79853f29447469a93bedff (diff)
downloadexternal_chromium-b922201e41fa263ae6bc159713907e4a9b340ba8.zip
external_chromium-b922201e41fa263ae6bc159713907e4a9b340ba8.tar.gz
external_chromium-b922201e41fa263ae6bc159713907e4a9b340ba8.tar.bz2
Adding missing files to webkit/glue
Change-Id: I4aaf5edd697c73913a1bc16c686bbb969d417380
Diffstat (limited to 'webkit/glue/plugins')
-rw-r--r--webkit/glue/plugins/pepper_audio.cc226
-rw-r--r--webkit/glue/plugins/pepper_audio.h113
-rw-r--r--webkit/glue/plugins/pepper_char_set.cc166
-rw-r--r--webkit/glue/plugins/pepper_char_set.h21
-rw-r--r--webkit/glue/plugins/pepper_cursor_control.cc91
-rw-r--r--webkit/glue/plugins/pepper_cursor_control.h19
-rw-r--r--webkit/glue/plugins/pepper_error_util.cc32
-rw-r--r--webkit/glue/plugins/pepper_error_util.h16
-rw-r--r--webkit/glue/plugins/pepper_fullscreen_container.h33
-rw-r--r--webkit/glue/plugins/pepper_graphics_2d.cc563
-rw-r--r--webkit/glue/plugins/pepper_graphics_2d.h180
-rw-r--r--webkit/glue/plugins/pepper_graphics_3d.cc256
-rw-r--r--webkit/glue/plugins/pepper_graphics_3d.h85
-rw-r--r--webkit/glue/plugins/pepper_graphics_3d_gl.cc716
-rw-r--r--webkit/glue/plugins/pepper_plugin_object.cc601
-rw-r--r--webkit/glue/plugins/pepper_plugin_object.h89
-rw-r--r--webkit/glue/plugins/pepper_private2.cc32
-rw-r--r--webkit/glue/plugins/pepper_private2.h23
-rw-r--r--webkit/glue/plugins/pepper_transport.cc139
-rw-r--r--webkit/glue/plugins/pepper_transport.h35
-rw-r--r--webkit/glue/plugins/pepper_url_util.cc176
-rw-r--r--webkit/glue/plugins/pepper_url_util.h19
-rw-r--r--webkit/glue/plugins/pepper_video_decoder.cc140
-rw-r--r--webkit/glue/plugins/pepper_video_decoder.h50
-rw-r--r--webkit/glue/plugins/ppb_private2.h21
25 files changed, 3842 insertions, 0 deletions
diff --git a/webkit/glue/plugins/pepper_audio.cc b/webkit/glue/plugins/pepper_audio.cc
new file mode 100644
index 0000000..3babc2f
--- /dev/null
+++ b/webkit/glue/plugins/pepper_audio.cc
@@ -0,0 +1,226 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/glue/plugins/pepper_audio.h"
+
+#include "base/logging.h"
+#include "third_party/ppapi/c/dev/ppb_audio_dev.h"
+#include "third_party/ppapi/c/dev/ppb_audio_trusted_dev.h"
+
+namespace pepper {
+
+namespace {
+
+// PPB_AudioConfig functions
+
+PP_Resource CreateStereo16bit(PP_Module module_id, uint32_t sample_rate,
+ uint32_t sample_frame_count) {
+ PluginModule* module = PluginModule::FromPPModule(module_id);
+ if (!module)
+ return 0;
+
+ scoped_refptr<AudioConfig> config(new AudioConfig(module, sample_rate,
+ sample_frame_count));
+ return config->GetReference();
+}
+
+uint32_t GetSampleRate(PP_Resource config_id) {
+ scoped_refptr<AudioConfig> config = Resource::GetAs<AudioConfig>(config_id);
+ return config ? config->sample_rate() : 0;
+}
+
+uint32_t GetSampleFrameCount(PP_Resource config_id) {
+ scoped_refptr<AudioConfig> config = Resource::GetAs<AudioConfig>(config_id);
+ return config ? config->sample_frame_count() : 0;
+}
+
+// PPB_Audio functions
+
+PP_Resource Create(PP_Instance instance_id, PP_Resource config_id,
+ PPB_Audio_Callback callback, void* user_data) {
+ PluginInstance* instance = PluginInstance::FromPPInstance(instance_id);
+ if (!instance)
+ return 0;
+ // TODO(neb): Require callback to be present for untrusted plugins.
+ scoped_refptr<Audio> audio(new Audio(instance->module()));
+ if (!audio->Init(instance->delegate(), config_id, callback, user_data))
+ return 0;
+ return audio->GetReference();
+}
+
+PP_Resource GetCurrentConfiguration(PP_Resource audio_id) {
+ scoped_refptr<Audio> audio = Resource::GetAs<Audio>(audio_id);
+ return audio ? audio->GetCurrentConfiguration() : 0;
+}
+
+bool StartPlayback(PP_Resource audio_id) {
+ scoped_refptr<Audio> audio = Resource::GetAs<Audio>(audio_id);
+ return audio ? audio->StartPlayback() : false;
+}
+
+bool StopPlayback(PP_Resource audio_id) {
+ scoped_refptr<Audio> audio = Resource::GetAs<Audio>(audio_id);
+ return audio ? audio->StopPlayback() : false;
+}
+
+// PPB_AudioTrusted functions
+
+PP_Resource GetBuffer(PP_Resource audio_id) {
+ // TODO(neb): Implement me!
+ return 0;
+}
+
+int GetOSDescriptor(PP_Resource audio_id) {
+ // TODO(neb): Implement me!
+ return -1;
+}
+
+const PPB_AudioConfig_Dev ppb_audioconfig = {
+ &CreateStereo16bit,
+ &GetSampleRate,
+ &GetSampleFrameCount
+};
+
+const PPB_Audio_Dev ppb_audio = {
+ &Create,
+ &GetCurrentConfiguration,
+ &StartPlayback,
+ &StopPlayback,
+};
+
+const PPB_AudioTrusted_Dev ppb_audiotrusted = {
+ &GetBuffer,
+ &GetOSDescriptor
+};
+
+} // namespace
+
+AudioConfig::AudioConfig(PluginModule* module, int32_t sample_rate,
+ int32_t sample_frame_count)
+ : Resource(module),
+ sample_rate_(sample_rate),
+ sample_frame_count_(sample_frame_count) {
+}
+
+const PPB_AudioConfig_Dev* AudioConfig::GetInterface() {
+ return &ppb_audioconfig;
+}
+
+AudioConfig* AudioConfig::AsAudioConfig() {
+ return this;
+}
+
+Audio::Audio(PluginModule* module)
+ : Resource(module),
+ playing_(false),
+ socket_(NULL),
+ shared_memory_(NULL),
+ shared_memory_size_(0),
+ callback_(NULL),
+ user_data_(NULL) {
+}
+
+Audio::~Audio() {
+ // Calling ShutDown() makes sure StreamCreated cannot be called anymore.
+ audio_->ShutDown();
+ // Closing the socket causes the thread to exit - wait for it.
+ socket_->Close();
+ if (audio_thread_.get()) {
+ audio_thread_->Join();
+ audio_thread_.reset();
+ }
+ // Shared memory destructor will unmap the memory automatically.
+}
+
+
+const PPB_Audio_Dev* Audio::GetInterface() {
+ return &ppb_audio;
+}
+
+const PPB_AudioTrusted_Dev* Audio::GetTrustedInterface() {
+ return &ppb_audiotrusted;
+}
+
+Audio* Audio::AsAudio() {
+ return this;
+}
+
+bool Audio::Init(PluginDelegate* plugin_delegate, PP_Resource config_id,
+ PPB_Audio_Callback callback, void* user_data) {
+ CHECK(!audio_.get());
+ config_ = Resource::GetAs<AudioConfig>(config_id);
+ if (!config_)
+ return false;
+ callback_ = callback;
+ user_data_ = user_data;
+ // When the stream is created, we'll get called back in StreamCreated().
+ audio_.reset(plugin_delegate->CreateAudio(config_->sample_rate(),
+ config_->sample_frame_count(),
+ this));
+ return audio_.get() != NULL;
+}
+
+bool Audio::StartPlayback() {
+ if (playing_)
+ return true;
+
+ CHECK(!audio_thread_.get());
+ if (callback_ && socket_.get()) {
+ audio_thread_.reset(new base::DelegateSimpleThread(this,
+ "plugin_audio_thread"));
+ audio_thread_->Start();
+ }
+ playing_ = true;
+ return audio_->StartPlayback();
+}
+
+bool Audio::StopPlayback() {
+ if (!playing_)
+ return true;
+
+ if (!audio_->StopPlayback())
+ return false;
+
+ if (audio_thread_.get()) {
+ audio_thread_->Join();
+ audio_thread_.reset();
+ }
+ playing_ = false;
+ return true;
+}
+
+void Audio::StreamCreated(base::SharedMemoryHandle shared_memory_handle,
+ size_t shared_memory_size,
+ base::SyncSocket::Handle socket_handle) {
+ socket_.reset(new base::SyncSocket(socket_handle));
+ shared_memory_.reset(new base::SharedMemory(shared_memory_handle, false));
+ shared_memory_size_ = shared_memory_size;
+
+ if (callback_) {
+ shared_memory_->Map(shared_memory_size_);
+ // In common case StartPlayback() was called before StreamCreated().
+ if (playing_) {
+ audio_thread_.reset(new base::DelegateSimpleThread(this,
+ "plugin_audio_thread"));
+ audio_thread_->Start();
+ }
+ }
+}
+
+void Audio::Run() {
+ int pending_data;
+ void* buffer = shared_memory_->memory();
+
+ while (sizeof(pending_data) ==
+ socket_->Receive(&pending_data, sizeof(pending_data)) &&
+ pending_data >= 0) {
+ // Exit the thread on pause.
+ if (pending_data < 0)
+ return;
+ callback_(buffer, user_data_);
+ }
+}
+
+} // namespace pepper
+
diff --git a/webkit/glue/plugins/pepper_audio.h b/webkit/glue/plugins/pepper_audio.h
new file mode 100644
index 0000000..d9a9e86
--- /dev/null
+++ b/webkit/glue/plugins/pepper_audio.h
@@ -0,0 +1,113 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "base/shared_memory.h"
+#include "base/simple_thread.h"
+#include "base/sync_socket.h"
+#include "third_party/ppapi/c/dev/ppb_audio_dev.h"
+#include "third_party/ppapi/c/dev/ppb_audio_config_dev.h"
+#include "third_party/ppapi/c/dev/ppb_audio_trusted_dev.h"
+#include "webkit/glue/plugins/pepper_plugin_delegate.h"
+#include "webkit/glue/plugins/pepper_plugin_instance.h"
+#include "webkit/glue/plugins/pepper_plugin_module.h"
+#include "webkit/glue/plugins/pepper_resource.h"
+
+#ifndef WEBKIT_GLUE_PLUGINS_PEPPER_DEVICE_CONTEXT_AUDIO_H_
+#define WEBKIT_GLUE_PLUGINS_PEPPER_DEVICE_CONTEXT_AUDIO_H_
+
+namespace pepper {
+
+class PluginInstance;
+class PluginModule;
+
+class AudioConfig : public Resource {
+ public:
+ AudioConfig(PluginModule* module, int32_t sample_rate,
+ int32_t sample_frame_count);
+
+ static const PPB_AudioConfig_Dev* GetInterface();
+
+ uint32_t sample_rate() { return sample_rate_; }
+ uint32_t sample_frame_count() { return sample_frame_count_; }
+
+ private:
+ // Resource override.
+ virtual AudioConfig* AsAudioConfig();
+
+ int sample_rate_;
+ int sample_frame_count_;
+};
+
+class Audio : public Resource,
+ public PluginDelegate::PlatformAudio::Client,
+ public base::DelegateSimpleThread::Delegate {
+ public:
+ explicit Audio(PluginModule* module);
+ virtual ~Audio();
+
+ static const PPB_Audio_Dev* GetInterface();
+ static const PPB_AudioTrusted_Dev* GetTrustedInterface();
+
+ bool Init(PluginDelegate* plugin_delegate, PP_Resource config_id,
+ PPB_Audio_Callback callback, void* user_data);
+
+ PP_Resource GetCurrentConfiguration() {
+ return config_->GetReference();
+ }
+
+ bool StartPlayback();
+
+ bool StopPlayback();
+
+ // Resource override.
+ virtual Audio* AsAudio();
+
+ private:
+ // pepper::PluginDelegate::PlatformAudio::Client implementation.
+ virtual void StreamCreated(base::SharedMemoryHandle shared_memory_handle,
+ size_t shared_memory_size_,
+ base::SyncSocket::Handle socket);
+ // End of pepper::PluginDelegate::PlatformAudio::Client implementation.
+
+ // Audio thread. DelegateSimpleThread::Delegate implementation.
+ virtual void Run();
+ // End of DelegateSimpleThread::Delegate implementation.
+
+ // True if playing the stream.
+ bool playing_;
+
+ // AudioConfig used for creating this Audio object.
+ scoped_refptr<AudioConfig> config_;
+
+ // PluginDelegate audio object that we delegate audio IPC through.
+ scoped_ptr<PluginDelegate::PlatformAudio> audio_;
+
+ // Socket used to notify us when audio is ready to accept new samples. This
+ // pointer is created in StreamCreated().
+ scoped_ptr<base::SyncSocket> socket_;
+
+ // Sample buffer in shared memory. This pointer is created in
+ // StreamCreated(). The memory is only mapped when the audio thread is
+ // created.
+ scoped_ptr<base::SharedMemory> shared_memory_;
+
+ // The size of the sample buffer in bytes.
+ size_t shared_memory_size_;
+
+ // When the callback is set, this thread is spawned for calling it.
+ scoped_ptr<base::DelegateSimpleThread> audio_thread_;
+
+ // Callback to call when audio is ready to accept new samples.
+ volatile PPB_Audio_Callback callback_;
+
+ // User data pointer passed verbatim to the callback function.
+ void* user_data_;
+};
+
+} // namespace pepper
+
+#endif // WEBKIT_GLUE_PLUGINS_PEPPER_DEVICE_CONTEXT_AUDIO_H_
+
diff --git a/webkit/glue/plugins/pepper_char_set.cc b/webkit/glue/plugins/pepper_char_set.cc
new file mode 100644
index 0000000..1e5fc0a
--- /dev/null
+++ b/webkit/glue/plugins/pepper_char_set.cc
@@ -0,0 +1,166 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/glue/plugins/pepper_char_set.h"
+
+#include <stdlib.h>
+
+#include "base/i18n/icu_string_conversions.h"
+#include "third_party/ppapi/c/dev/ppb_char_set_dev.h"
+#include "unicode/ucnv.h"
+#include "unicode/ucnv_cb.h"
+#include "unicode/ucnv_err.h"
+#include "unicode/ustring.h"
+#include "webkit/glue/plugins/pepper_plugin_delegate.h"
+#include "webkit/glue/plugins/pepper_plugin_instance.h"
+#include "webkit/glue/plugins/pepper_plugin_module.h"
+#include "webkit/glue/plugins/pepper_var.h"
+
+namespace pepper {
+
+namespace {
+
+// Converts the given PP error handling behavior to the version in base,
+// placing the result in |*result| and returning true on success. Returns false
+// if the enum is invalid.
+bool PPToBaseConversionError(PP_CharSet_ConversionError on_error,
+ base::OnStringConversionError::Type* result) {
+ switch (on_error) {
+ case PP_CHARSET_CONVERSIONERROR_FAIL:
+ *result = base::OnStringConversionError::FAIL;
+ return true;
+ case PP_CHARSET_CONVERSIONERROR_SKIP:
+ *result = base::OnStringConversionError::SKIP;
+ return true;
+ case PP_CHARSET_CONVERSIONERROR_SUBSTITUTE:
+ *result = base::OnStringConversionError::SUBSTITUTE;
+ return true;
+ default:
+ return false;
+ }
+}
+
+// The "substitution" behavior of this function does not match the
+// implementation in base, so we partially duplicate the code from
+// icu_string_conversions.cc with the correct error handling setup required
+// by this pepper interface.
+char* UTF16ToCharSet(const uint16_t* utf16, uint32_t utf16_len,
+ const char* output_char_set,
+ PP_CharSet_ConversionError on_error,
+ uint32_t* output_length) {
+ *output_length = 0;
+
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter* converter = ucnv_open(output_char_set, &status);
+ if (!U_SUCCESS(status))
+ return NULL;
+
+ int encoded_max_length = UCNV_GET_MAX_BYTES_FOR_STRING(utf16_len,
+ ucnv_getMaxCharSize(converter));
+
+ // Setup our error handler.
+ switch (on_error) {
+ case PP_CHARSET_CONVERSIONERROR_FAIL:
+ ucnv_setFromUCallBack(converter, UCNV_FROM_U_CALLBACK_STOP, 0,
+ NULL, NULL, &status);
+ break;
+ case PP_CHARSET_CONVERSIONERROR_SKIP:
+ ucnv_setFromUCallBack(converter, UCNV_FROM_U_CALLBACK_SKIP, 0,
+ NULL, NULL, &status);
+ break;
+ case PP_CHARSET_CONVERSIONERROR_SUBSTITUTE: {
+ // ICU sets the substitution char for some character sets (like latin1)
+ // to be the ASCII "substitution character" (26). We want to use '?'
+ // instead for backwards-compat with Windows behavior.
+ char subst_chars[32];
+ int8_t subst_chars_len = 32;
+ ucnv_getSubstChars(converter, subst_chars, &subst_chars_len, &status);
+ if (subst_chars_len == 1 && subst_chars[0] == 26) {
+ // Override to the question mark character if possible. When using
+ // setSubstString, the input is a Unicode character. The function will
+ // try to convert it to the destination character set and fail if that
+ // can not be converted to the destination character set.
+ //
+ // We just ignore any failure. If the dest char set has no
+ // representation for '?', then we'll just stick to the ICU default
+ // substitution character.
+ UErrorCode subst_status = U_ZERO_ERROR;
+ UChar question_mark = '?';
+ ucnv_setSubstString(converter, &question_mark, 1, &subst_status);
+ }
+
+ ucnv_setFromUCallBack(converter, UCNV_FROM_U_CALLBACK_SUBSTITUTE, 0,
+ NULL, NULL, &status);
+ break;
+ }
+ default:
+ return NULL;
+ }
+
+ // ucnv_fromUChars returns size not including terminating null.
+ char* encoded = static_cast<char*>(malloc(encoded_max_length + 1));
+ int actual_size = ucnv_fromUChars(converter, encoded,
+ encoded_max_length, reinterpret_cast<const UChar*>(utf16), utf16_len,
+ &status);
+ ucnv_close(converter);
+ if (!U_SUCCESS(status)) {
+ free(encoded);
+ return NULL;
+ }
+ encoded[actual_size] = 0;
+ *output_length = actual_size;
+ return encoded;
+}
+
+uint16_t* CharSetToUTF16(const char* input, uint32_t input_len,
+ const char* input_char_set,
+ PP_CharSet_ConversionError on_error,
+ uint32_t* output_length) {
+ *output_length = 0;
+
+ base::OnStringConversionError::Type base_on_error;
+ if (!PPToBaseConversionError(on_error, &base_on_error))
+ return NULL; // Invalid enum value.
+
+ // We can convert this call to the implementation in base to avoid code
+ // duplication, although this does introduce an extra copy of the data.
+ string16 output;
+ if (!base::CodepageToUTF16(std::string(input, input_len), input_char_set,
+ base_on_error, &output))
+ return NULL;
+
+ uint16_t* ret_buf = static_cast<uint16_t*>(
+ malloc((output.size() + 1) * sizeof(uint16_t)));
+ if (!ret_buf)
+ return NULL;
+
+ *output_length = static_cast<uint32_t>(output.size());
+ memcpy(ret_buf, output.c_str(), (output.size() + 1) * sizeof(uint16_t));
+ return ret_buf;
+}
+
+PP_Var GetDefaultCharSet(PP_Module pp_module) {
+ PluginModule* module = PluginModule::FromPPModule(pp_module);
+ if (!module)
+ return PP_MakeVoid();
+
+ std::string encoding =
+ module->GetSomeInstance()->delegate()->GetDefaultEncoding();
+ return StringVar::StringToPPVar(module, encoding);
+}
+
+const PPB_CharSet_Dev ppb_charset = {
+ &UTF16ToCharSet,
+ &CharSetToUTF16,
+ &GetDefaultCharSet
+};
+
+} // namespace
+
+// static
+const struct PPB_CharSet_Dev* CharSet::GetInterface() {
+ return &ppb_charset;
+}
+
+} // namespace pepper
diff --git a/webkit/glue/plugins/pepper_char_set.h b/webkit/glue/plugins/pepper_char_set.h
new file mode 100644
index 0000000..5abb54d
--- /dev/null
+++ b/webkit/glue/plugins/pepper_char_set.h
@@ -0,0 +1,21 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_GLUE_PLUGINS_PEPPER_CHAR_SET_H_
+#define WEBKIT_GLUE_PLUGINS_PEPPER_CHAR_SET_H_
+
+struct PPB_CharSet_Dev;
+
+namespace pepper {
+
+class CharSet {
+ public:
+ // Returns a pointer to the interface implementing PPB_CharSet that is
+ // exposed to the plugin.
+ static const PPB_CharSet_Dev* GetInterface();
+};
+
+} // namespace pepper
+
+#endif // WEBKIT_GLUE_PLUGINS_PEPPER_CHAR_SET_H_
diff --git a/webkit/glue/plugins/pepper_cursor_control.cc b/webkit/glue/plugins/pepper_cursor_control.cc
new file mode 100644
index 0000000..de3c166
--- /dev/null
+++ b/webkit/glue/plugins/pepper_cursor_control.cc
@@ -0,0 +1,91 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/glue/plugins/pepper_cursor_control.h"
+
+#include "base/logging.h"
+#include "base/ref_counted.h"
+#include "third_party/ppapi/c/dev/pp_cursor_type_dev.h"
+#include "third_party/ppapi/c/dev/ppb_cursor_control_dev.h"
+#include "third_party/ppapi/c/pp_point.h"
+#include "third_party/ppapi/c/pp_resource.h"
+#include "webkit/glue/plugins/pepper_image_data.h"
+#include "webkit/glue/plugins/pepper_plugin_instance.h"
+#include "webkit/glue/plugins/pepper_resource.h"
+
+namespace pepper {
+
+namespace {
+
+bool SetCursor(PP_Instance instance_id,
+ PP_CursorType_Dev type,
+ PP_Resource custom_image_id,
+ const PP_Point* hot_spot) {
+ PluginInstance* instance = PluginInstance::FromPPInstance(instance_id);
+ if (!instance)
+ return false;
+
+ scoped_refptr<ImageData> custom_image(
+ Resource::GetAs<ImageData>(custom_image_id));
+ if (custom_image.get()) {
+ // TODO(neb): implement custom cursors.
+ NOTIMPLEMENTED();
+ return false;
+ }
+
+ return instance->SetCursor(type);
+}
+
+bool LockCursor(PP_Instance instance_id) {
+ PluginInstance* instance = PluginInstance::FromPPInstance(instance_id);
+ if (!instance)
+ return false;
+
+ // TODO(neb): implement cursor locking.
+ return false;
+}
+
+bool UnlockCursor(PP_Instance instance_id) {
+ PluginInstance* instance = PluginInstance::FromPPInstance(instance_id);
+ if (!instance)
+ return false;
+
+ // TODO(neb): implement cursor locking.
+ return false;
+}
+
+bool HasCursorLock(PP_Instance instance_id) {
+ PluginInstance* instance = PluginInstance::FromPPInstance(instance_id);
+ if (!instance)
+ return false;
+
+ // TODO(neb): implement cursor locking.
+ return false;
+}
+
+bool CanLockCursor(PP_Instance instance_id) {
+ PluginInstance* instance = PluginInstance::FromPPInstance(instance_id);
+ if (!instance)
+ return false;
+
+ // TODO(neb): implement cursor locking.
+ return false;
+}
+
+const PPB_CursorControl_Dev cursor_control_interface = {
+ &SetCursor,
+ &LockCursor,
+ &UnlockCursor,
+ &HasCursorLock,
+ &CanLockCursor
+};
+
+} // namespace
+
+const PPB_CursorControl_Dev* GetCursorControlInterface() {
+ return &cursor_control_interface;
+}
+
+} // namespace pepper
+
diff --git a/webkit/glue/plugins/pepper_cursor_control.h b/webkit/glue/plugins/pepper_cursor_control.h
new file mode 100644
index 0000000..693fb4a
--- /dev/null
+++ b/webkit/glue/plugins/pepper_cursor_control.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_GLUE_PLUGINS_PEPPER_CURSOR_CONTROL_H_
+#define WEBKIT_GLUE_PLUGINS_PEPPER_CURSOR_CONTROL_H_
+
+struct PPB_CursorControl_Dev;
+
+namespace pepper {
+
+// There's no class implementing CursorControl so we just expose a getter for
+// the interface implemented in the .cc file here.
+const PPB_CursorControl_Dev* GetCursorControlInterface();
+
+} // namespace pepper
+
+#endif // WEBKIT_GLUE_PLUGINS_PEPPER_CURSOR_CONTROL_H_
+
diff --git a/webkit/glue/plugins/pepper_error_util.cc b/webkit/glue/plugins/pepper_error_util.cc
new file mode 100644
index 0000000..a1b5c06
--- /dev/null
+++ b/webkit/glue/plugins/pepper_error_util.cc
@@ -0,0 +1,32 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/glue/plugins/pepper_error_util.h"
+
+#include "third_party/ppapi/c/pp_errors.h"
+
+namespace pepper {
+
+int PlatformFileErrorToPepperError(base::PlatformFileError error_code) {
+ switch (error_code) {
+ case base::PLATFORM_FILE_OK:
+ return PP_OK;
+ case base::PLATFORM_FILE_ERROR_EXISTS:
+ return PP_ERROR_FILEEXISTS;
+ case base::PLATFORM_FILE_ERROR_NOT_FOUND:
+ return PP_ERROR_FILENOTFOUND;
+ case base::PLATFORM_FILE_ERROR_ACCESS_DENIED:
+ return PP_ERROR_NOACCESS;
+ case base::PLATFORM_FILE_ERROR_NO_MEMORY:
+ return PP_ERROR_NOMEMORY;
+ case base::PLATFORM_FILE_ERROR_NO_SPACE:
+ return PP_ERROR_NOSPACE;
+ case base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY:
+ return PP_ERROR_FAILED;
+ default:
+ return PP_ERROR_FAILED;
+ }
+}
+
+} // namespace pepper
diff --git a/webkit/glue/plugins/pepper_error_util.h b/webkit/glue/plugins/pepper_error_util.h
new file mode 100644
index 0000000..12e715c
--- /dev/null
+++ b/webkit/glue/plugins/pepper_error_util.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_GLUE_PLUGINS_PEPPER_ERROR_UTIL_H_
+#define WEBKIT_GLUE_PLUGINS_PEPPER_ERROR_UTIL_H_
+
+#include "base/platform_file.h"
+
+namespace pepper {
+
+int PlatformFileErrorToPepperError(base::PlatformFileError error_code);
+
+} // namespace pepper
+
+#endif // WEBKIT_GLUE_PLUGINS_PEPPER_ERROR_UTIL_H_
diff --git a/webkit/glue/plugins/pepper_fullscreen_container.h b/webkit/glue/plugins/pepper_fullscreen_container.h
new file mode 100644
index 0000000..5f67538
--- /dev/null
+++ b/webkit/glue/plugins/pepper_fullscreen_container.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_GLUE_PLUGINS_PEPPER_FULLSCREEN_CONTAINER_H_
+#define WEBKIT_GLUE_PLUGINS_PEPPER_FULLSCREEN_CONTAINER_H_
+
+namespace WebKit {
+struct WebRect;
+} // namespace WebKit
+
+namespace pepper {
+
+// This class is like a lightweight WebPluginContainer for fullscreen pepper
+// plugins, that only handles painting.
+class FullscreenContainer {
+ public:
+ virtual ~FullscreenContainer() {}
+
+ // Invalidates the full plugin region.
+ virtual void Invalidate() = 0;
+
+ // Invalidates a partial region of the plugin.
+ virtual void InvalidateRect(const WebKit::WebRect&) = 0;
+
+ // Destroys the fullscreen window. This also destroys the FullscreenContainer
+ // instance.
+ virtual void Destroy() = 0;
+};
+
+} // namespace pepper
+
+#endif // WEBKIT_GLUE_PLUGINS_PEPPER_FULLSCREEN_CONTAINER_H_
diff --git a/webkit/glue/plugins/pepper_graphics_2d.cc b/webkit/glue/plugins/pepper_graphics_2d.cc
new file mode 100644
index 0000000..5011f87
--- /dev/null
+++ b/webkit/glue/plugins/pepper_graphics_2d.cc
@@ -0,0 +1,563 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/glue/plugins/pepper_graphics_2d.h"
+
+#include <iterator>
+
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/task.h"
+#include "gfx/blit.h"
+#include "gfx/point.h"
+#include "gfx/rect.h"
+#include "skia/ext/platform_canvas.h"
+#include "third_party/ppapi/c/pp_errors.h"
+#include "third_party/ppapi/c/pp_module.h"
+#include "third_party/ppapi/c/pp_rect.h"
+#include "third_party/ppapi/c/pp_resource.h"
+#include "third_party/ppapi/c/ppb_graphics_2d.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "webkit/glue/plugins/pepper_image_data.h"
+#include "webkit/glue/plugins/pepper_plugin_instance.h"
+#include "webkit/glue/plugins/pepper_plugin_module.h"
+
+#if defined(OS_MACOSX)
+#include "base/mac_util.h"
+#include "base/scoped_cftyperef.h"
+#endif
+
+namespace pepper {
+
+namespace {
+
+// Converts a rect inside an image of the given dimensions. The rect may be
+// NULL to indicate it should be the entire image. If the rect is outside of
+// the image, this will do nothing and return false.
+bool ValidateAndConvertRect(const PP_Rect* rect,
+ int image_width, int image_height,
+ gfx::Rect* dest) {
+ if (!rect) {
+ // Use the entire image area.
+ *dest = gfx::Rect(0, 0, image_width, image_height);
+ } else {
+ // Validate the passed-in area.
+ if (rect->point.x < 0 || rect->point.y < 0 ||
+ rect->size.width <= 0 || rect->size.height <= 0)
+ return false;
+
+ // Check the max bounds, being careful of overflow.
+ if (static_cast<int64>(rect->point.x) +
+ static_cast<int64>(rect->size.width) >
+ static_cast<int64>(image_width))
+ return false;
+ if (static_cast<int64>(rect->point.y) +
+ static_cast<int64>(rect->size.height) >
+ static_cast<int64>(image_height))
+ return false;
+
+ *dest = gfx::Rect(rect->point.x, rect->point.y,
+ rect->size.width, rect->size.height);
+ }
+ return true;
+}
+
+PP_Resource Create(PP_Module module_id,
+ const PP_Size* size,
+ bool is_always_opaque) {
+ PluginModule* module = PluginModule::FromPPModule(module_id);
+ if (!module)
+ return 0;
+
+ scoped_refptr<Graphics2D> context(new Graphics2D(module));
+ if (!context->Init(size->width, size->height, is_always_opaque))
+ return 0;
+ return context->GetReference();
+}
+
+bool IsGraphics2D(PP_Resource resource) {
+ return !!Resource::GetAs<Graphics2D>(resource);
+}
+
+bool Describe(PP_Resource device_context,
+ PP_Size* size,
+ bool* is_always_opaque) {
+ scoped_refptr<Graphics2D> context(
+ Resource::GetAs<Graphics2D>(device_context));
+ if (!context)
+ return false;
+ return context->Describe(size, is_always_opaque);
+}
+
+bool PaintImageData(PP_Resource device_context,
+ PP_Resource image,
+ const PP_Point* top_left,
+ const PP_Rect* src_rect) {
+ scoped_refptr<Graphics2D> context(
+ Resource::GetAs<Graphics2D>(device_context));
+ if (!context)
+ return false;
+ return context->PaintImageData(image, top_left, src_rect);
+}
+
+bool Scroll(PP_Resource device_context,
+ const PP_Rect* clip_rect,
+ const PP_Point* amount) {
+ scoped_refptr<Graphics2D> context(
+ Resource::GetAs<Graphics2D>(device_context));
+ if (!context)
+ return false;
+ return context->Scroll(clip_rect, amount);
+}
+
+bool ReplaceContents(PP_Resource device_context, PP_Resource image) {
+ scoped_refptr<Graphics2D> context(
+ Resource::GetAs<Graphics2D>(device_context));
+ if (!context)
+ return false;
+ return context->ReplaceContents(image);
+}
+
+int32_t Flush(PP_Resource device_context,
+ PP_CompletionCallback callback) {
+ scoped_refptr<Graphics2D> context(
+ Resource::GetAs<Graphics2D>(device_context));
+ if (!context)
+ return PP_ERROR_BADRESOURCE;
+ return context->Flush(callback);
+}
+
+const PPB_Graphics2D ppb_graphics_2d = {
+ &Create,
+ &IsGraphics2D,
+ &Describe,
+ &PaintImageData,
+ &Scroll,
+ &ReplaceContents,
+ &Flush
+};
+
+} // namespace
+
+struct Graphics2D::QueuedOperation {
+ enum Type {
+ PAINT,
+ SCROLL,
+ REPLACE
+ };
+
+ QueuedOperation(Type t)
+ : type(t),
+ paint_x(0),
+ paint_y(0),
+ scroll_dx(0),
+ scroll_dy(0) {
+ }
+
+ Type type;
+
+ // Valid when type == PAINT.
+ scoped_refptr<ImageData> paint_image;
+ int paint_x, paint_y;
+ gfx::Rect paint_src_rect;
+
+ // Valid when type == SCROLL.
+ gfx::Rect scroll_clip_rect;
+ int scroll_dx, scroll_dy;
+
+ // Valid when type == REPLACE.
+ scoped_refptr<ImageData> replace_image;
+};
+
+Graphics2D::Graphics2D(PluginModule* module)
+ : Resource(module),
+ bound_instance_(NULL),
+ flushed_any_data_(false),
+ offscreen_flush_pending_(false),
+ is_always_opaque_(false) {
+}
+
+Graphics2D::~Graphics2D() {
+}
+
+// static
+const PPB_Graphics2D* Graphics2D::GetInterface() {
+ return &ppb_graphics_2d;
+}
+
+bool Graphics2D::Init(int width, int height, bool is_always_opaque) {
+ // The underlying ImageData will validate the dimensions.
+ image_data_ = new ImageData(module());
+ if (!image_data_->Init(PP_IMAGEDATAFORMAT_BGRA_PREMUL, width, height, true) ||
+ !image_data_->Map()) {
+ image_data_ = NULL;
+ return false;
+ }
+ is_always_opaque_ = is_always_opaque;
+ return true;
+}
+
+bool Graphics2D::Describe(PP_Size* size, bool* is_always_opaque) {
+ size->width = image_data_->width();
+ size->height = image_data_->height();
+ *is_always_opaque = false; // TODO(brettw) implement this.
+ return true;
+}
+
+bool Graphics2D::PaintImageData(PP_Resource image,
+ const PP_Point* top_left,
+ const PP_Rect* src_rect) {
+ if (!top_left)
+ return false;
+
+ scoped_refptr<ImageData> image_resource(Resource::GetAs<ImageData>(image));
+ if (!image_resource)
+ return false;
+
+ QueuedOperation operation(QueuedOperation::PAINT);
+ operation.paint_image = image_resource;
+ if (!ValidateAndConvertRect(src_rect, image_resource->width(),
+ image_resource->height(),
+ &operation.paint_src_rect))
+ return false;
+
+ // Validate the bitmap position using the previously-validated rect, there
+ // should be no painted area outside of the image.
+ int64 x64 = static_cast<int64>(top_left->x);
+ int64 y64 = static_cast<int64>(top_left->y);
+ if (x64 + static_cast<int64>(operation.paint_src_rect.x()) < 0 ||
+ x64 + static_cast<int64>(operation.paint_src_rect.right()) >
+ image_data_->width())
+ return false;
+ if (y64 + static_cast<int64>(operation.paint_src_rect.y()) < 0 ||
+ y64 + static_cast<int64>(operation.paint_src_rect.bottom()) >
+ image_data_->height())
+ return false;
+ operation.paint_x = top_left->x;
+ operation.paint_y = top_left->y;
+
+ queued_operations_.push_back(operation);
+ return true;
+}
+
+bool Graphics2D::Scroll(const PP_Rect* clip_rect, const PP_Point* amount) {
+ QueuedOperation operation(QueuedOperation::SCROLL);
+ if (!ValidateAndConvertRect(clip_rect,
+ image_data_->width(),
+ image_data_->height(),
+ &operation.scroll_clip_rect))
+ return false;
+
+ // If we're being asked to scroll by more than the clip rect size, just
+ // ignore this scroll command and say it worked.
+ int32 dx = amount->x;
+ int32 dy = amount->y;
+ if (dx <= -image_data_->width() || dx >= image_data_->width() ||
+ dx <= -image_data_->height() || dy >= image_data_->height())
+ return true;
+
+ operation.scroll_dx = dx;
+ operation.scroll_dy = dy;
+
+ queued_operations_.push_back(operation);
+ return false;
+}
+
+bool Graphics2D::ReplaceContents(PP_Resource image) {
+ scoped_refptr<ImageData> image_resource(Resource::GetAs<ImageData>(image));
+ if (!image_resource)
+ return false;
+ if (image_resource->format() != PP_IMAGEDATAFORMAT_BGRA_PREMUL)
+ return false;
+
+ if (image_resource->width() != image_data_->width() ||
+ image_resource->height() != image_data_->height())
+ return false;
+
+ QueuedOperation operation(QueuedOperation::REPLACE);
+ operation.replace_image = image_resource;
+ queued_operations_.push_back(operation);
+
+ return true;
+}
+
+int32_t Graphics2D::Flush(const PP_CompletionCallback& callback) {
+ // Don't allow more than one pending flush at a time.
+ if (HasPendingFlush())
+ return PP_ERROR_INPROGRESS;
+
+ // TODO(brettw) check that the current thread is not the main one and
+ // implement blocking flushes in this case.
+ if (!callback.func)
+ return PP_ERROR_BADARGUMENT;
+
+ gfx::Rect changed_rect;
+ for (size_t i = 0; i < queued_operations_.size(); i++) {
+ QueuedOperation& operation = queued_operations_[i];
+ gfx::Rect op_rect;
+ switch (operation.type) {
+ case QueuedOperation::PAINT:
+ ExecutePaintImageData(operation.paint_image,
+ operation.paint_x, operation.paint_y,
+ operation.paint_src_rect,
+ &op_rect);
+ break;
+ case QueuedOperation::SCROLL:
+ ExecuteScroll(operation.scroll_clip_rect,
+ operation.scroll_dx, operation.scroll_dy,
+ &op_rect);
+ break;
+ case QueuedOperation::REPLACE:
+ ExecuteReplaceContents(operation.replace_image, &op_rect);
+ break;
+ }
+ changed_rect = changed_rect.Union(op_rect);
+ }
+ queued_operations_.clear();
+ flushed_any_data_ = true;
+
+ // We need the rect to be in terms of the current clip rect of the plugin
+ // since that's what will actually be painted. If we issue an invalidate
+ // for a clipped-out region, WebKit will do nothing and we won't get any
+ // ViewInitiatedPaint/ViewFlushedPaint calls, leaving our callback stranded.
+ gfx::Rect visible_changed_rect;
+ if (bound_instance_ && !changed_rect.IsEmpty())
+ visible_changed_rect = bound_instance_->clip().Intersect(changed_rect);
+
+ if (bound_instance_ && !visible_changed_rect.IsEmpty()) {
+ unpainted_flush_callback_.Set(callback);
+ bound_instance_->InvalidateRect(visible_changed_rect);
+ } else {
+ // There's nothing visible to invalidate so just schedule the callback to
+ // execute in the next round of the message loop.
+ ScheduleOffscreenCallback(FlushCallbackData(callback));
+ }
+ return PP_ERROR_WOULDBLOCK;
+}
+
+bool Graphics2D::ReadImageData(PP_Resource image,
+ const PP_Point* top_left) {
+ // Get and validate the image object to paint into.
+ scoped_refptr<ImageData> image_resource(Resource::GetAs<ImageData>(image));
+ if (!image_resource)
+ return false;
+ if (image_resource->format() != PP_IMAGEDATAFORMAT_BGRA_PREMUL)
+ return false; // Must be in the right format.
+
+ // Validate the bitmap position.
+ int x = top_left->x;
+ if (x < 0 ||
+ static_cast<int64>(x) + static_cast<int64>(image_resource->width()) >
+ image_data_->width())
+ return false;
+ int y = top_left->y;
+ if (y < 0 ||
+ static_cast<int64>(y) + static_cast<int64>(image_resource->height()) >
+ image_data_->height())
+ return false;
+
+ ImageDataAutoMapper auto_mapper(image_resource);
+ if (!auto_mapper.is_valid())
+ return false;
+ skia::PlatformCanvas* dest_canvas = image_resource->mapped_canvas();
+
+ SkIRect src_irect = { x, y,
+ x + image_resource->width(),
+ y + image_resource->height() };
+ SkRect dest_rect = { SkIntToScalar(0),
+ SkIntToScalar(0),
+ SkIntToScalar(image_resource->width()),
+ SkIntToScalar(image_resource->height()) };
+
+ // We want to replace the contents of the bitmap rather than blend.
+ SkPaint paint;
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+ dest_canvas->drawBitmapRect(*image_data_->GetMappedBitmap(),
+ &src_irect, dest_rect, &paint);
+ return true;
+}
+
+bool Graphics2D::BindToInstance(PluginInstance* new_instance) {
+ if (bound_instance_ == new_instance)
+ return true; // Rebinding the same device, nothing to do.
+ if (bound_instance_ && new_instance)
+ return false; // Can't change a bound device.
+
+ if (!new_instance) {
+ // When the device is detached, we'll not get any more paint callbacks so
+ // we need to clear the list, but we still want to issue any pending
+ // callbacks to the plugin.
+ if (!unpainted_flush_callback_.is_null()) {
+ ScheduleOffscreenCallback(unpainted_flush_callback_);
+ unpainted_flush_callback_.Clear();
+ }
+ if (!painted_flush_callback_.is_null()) {
+ ScheduleOffscreenCallback(painted_flush_callback_);
+ painted_flush_callback_.Clear();
+ }
+ } else if (flushed_any_data_) {
+ // Only schedule a paint if this backing store has had any data flushed to
+ // it. This is an optimization. A "normal" plugin will first allocated a
+ // backing store, bind it, and then execute their normal painting and
+ // update loop. If binding a device always invalidated, it would mean we
+ // would get one paint for the bind, and one for the first time the plugin
+ // actually painted something. By not bothering to schedule an invalidate
+ // when an empty device is initially bound, we can save an extra paint for
+ // many plugins during the critical page initialization phase.
+ new_instance->InvalidateRect(gfx::Rect());
+ }
+
+ bound_instance_ = new_instance;
+ return true;
+}
+
+void Graphics2D::Paint(WebKit::WebCanvas* canvas,
+ const gfx::Rect& plugin_rect,
+ const gfx::Rect& paint_rect) {
+ // We're guaranteed to have a mapped canvas since we mapped it in Init().
+ const SkBitmap& backing_bitmap = *image_data_->GetMappedBitmap();
+
+#if defined(OS_MACOSX)
+ SkAutoLockPixels lock(backing_bitmap);
+
+ scoped_cftyperef<CGDataProviderRef> data_provider(
+ CGDataProviderCreateWithData(
+ NULL, backing_bitmap.getAddr32(0, 0),
+ backing_bitmap.rowBytes() * backing_bitmap.height(), NULL));
+ scoped_cftyperef<CGImageRef> image(
+ CGImageCreate(
+ backing_bitmap.width(), backing_bitmap.height(),
+ 8, 32, backing_bitmap.rowBytes(),
+ mac_util::GetSystemColorSpace(),
+ kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
+ data_provider, NULL, false, kCGRenderingIntentDefault));
+
+ // Flip the transform
+ CGContextSaveGState(canvas);
+ float window_height = static_cast<float>(CGBitmapContextGetHeight(canvas));
+ CGContextTranslateCTM(canvas, 0, window_height);
+ CGContextScaleCTM(canvas, 1.0, -1.0);
+
+ CGRect bounds;
+ bounds.origin.x = plugin_rect.origin().x();
+ bounds.origin.y = window_height - plugin_rect.origin().y() -
+ backing_bitmap.height();
+ bounds.size.width = backing_bitmap.width();
+ bounds.size.height = backing_bitmap.height();
+
+ // TODO(brettw) bug 56673: do a direct memcpy instead of going through CG
+ // if the is_always_opaque_ flag is set.
+
+ CGContextDrawImage(canvas, bounds, image);
+ CGContextRestoreGState(canvas);
+#else
+ SkPaint paint;
+ if (is_always_opaque_) {
+ // When we know the device is opaque, we can disable blending for slightly
+ // more optimized painting.
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+ }
+
+ gfx::Point origin(plugin_rect.origin().x(), plugin_rect.origin().y());
+ canvas->drawBitmap(backing_bitmap,
+ SkIntToScalar(plugin_rect.origin().x()),
+ SkIntToScalar(plugin_rect.origin().y()),
+ &paint);
+#endif
+}
+
+void Graphics2D::ViewInitiatedPaint() {
+ // Move any "unpainted" callback to the painted state. See
+ // |unpainted_flush_callback_| in the header for more.
+ if (!unpainted_flush_callback_.is_null()) {
+ DCHECK(painted_flush_callback_.is_null());
+ std::swap(painted_flush_callback_, unpainted_flush_callback_);
+ }
+}
+
+void Graphics2D::ViewFlushedPaint() {
+ // Notify any "painted" callback. See |unpainted_flush_callback_| in the
+ // header for more.
+ if (!painted_flush_callback_.is_null()) {
+ // We must clear this variable before issuing the callback. It will be
+ // common for the plugin to issue another invalidate in response to a flush
+ // callback, and we don't want to think that a callback is already pending.
+ FlushCallbackData callback;
+ std::swap(callback, painted_flush_callback_);
+ callback.Execute(PP_OK);
+ }
+}
+
+void Graphics2D::ExecutePaintImageData(ImageData* image,
+ int x, int y,
+ const gfx::Rect& src_rect,
+ gfx::Rect* invalidated_rect) {
+ // Ensure the source image is mapped to read from it.
+ ImageDataAutoMapper auto_mapper(image);
+ if (!auto_mapper.is_valid())
+ return;
+
+ // Portion within the source image to cut out.
+ SkIRect src_irect = { src_rect.x(), src_rect.y(),
+ src_rect.right(), src_rect.bottom() };
+
+ // Location within the backing store to copy to.
+ *invalidated_rect = src_rect;
+ invalidated_rect->Offset(x, y);
+ SkRect dest_rect = { SkIntToScalar(invalidated_rect->x()),
+ SkIntToScalar(invalidated_rect->y()),
+ SkIntToScalar(invalidated_rect->right()),
+ SkIntToScalar(invalidated_rect->bottom()) };
+
+ // We're guaranteed to have a mapped canvas since we mapped it in Init().
+ skia::PlatformCanvas* backing_canvas = image_data_->mapped_canvas();
+
+ // We want to replace the contents of the bitmap rather than blend.
+ SkPaint paint;
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+ backing_canvas->drawBitmapRect(*image->GetMappedBitmap(),
+ &src_irect, dest_rect, &paint);
+}
+
+void Graphics2D::ExecuteScroll(const gfx::Rect& clip, int dx, int dy,
+ gfx::Rect* invalidated_rect) {
+ gfx::ScrollCanvas(image_data_->mapped_canvas(),
+ clip, gfx::Point(dx, dy));
+ *invalidated_rect = clip;
+}
+
+void Graphics2D::ExecuteReplaceContents(ImageData* image,
+ gfx::Rect* invalidated_rect) {
+ image_data_->Swap(image);
+ *invalidated_rect = gfx::Rect(0, 0,
+ image_data_->width(), image_data_->height());
+}
+
+void Graphics2D::ScheduleOffscreenCallback(const FlushCallbackData& callback) {
+ DCHECK(!HasPendingFlush());
+ offscreen_flush_pending_ = true;
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ NewRunnableMethod(this,
+ &Graphics2D::ExecuteOffscreenCallback,
+ callback));
+}
+
+void Graphics2D::ExecuteOffscreenCallback(FlushCallbackData data) {
+ DCHECK(offscreen_flush_pending_);
+
+ // We must clear this flag before issuing the callback. It will be
+ // common for the plugin to issue another invalidate in response to a flush
+ // callback, and we don't want to think that a callback is already pending.
+ offscreen_flush_pending_ = false;
+ data.Execute(PP_OK);
+}
+
+bool Graphics2D::HasPendingFlush() const {
+ return !unpainted_flush_callback_.is_null() ||
+ !painted_flush_callback_.is_null() ||
+ offscreen_flush_pending_;
+}
+
+} // namespace pepper
diff --git a/webkit/glue/plugins/pepper_graphics_2d.h b/webkit/glue/plugins/pepper_graphics_2d.h
new file mode 100644
index 0000000..3af84de
--- /dev/null
+++ b/webkit/glue/plugins/pepper_graphics_2d.h
@@ -0,0 +1,180 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_GLUE_PLUGINS_PEPPER_GRAPHICS_2D_H_
+#define WEBKIT_GLUE_PLUGINS_PEPPER_GRAPHICS_2D_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "third_party/ppapi/c/pp_completion_callback.h"
+#include "third_party/ppapi/c/ppb_graphics_2d.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebCanvas.h"
+#include "webkit/glue/plugins/pepper_resource.h"
+
+struct PPB_Graphics2D;
+
+namespace gfx {
+class Rect;
+}
+
+namespace pepper {
+
+class ImageData;
+class PluginInstance;
+class PluginModule;
+
+class Graphics2D : public Resource {
+ public:
+ Graphics2D(PluginModule* module);
+ virtual ~Graphics2D();
+
+ // Returns a pointer to the interface implementing PPB_ImageData that is
+ // exposed to the plugin.
+ static const PPB_Graphics2D* GetInterface();
+
+ bool Init(int width, int height, bool is_always_opaque);
+
+ bool is_always_opaque() const { return is_always_opaque_; }
+
+ // Resource override.
+ virtual Graphics2D* AsGraphics2D() { return this; }
+
+ // PPB_Graphics2D functions.
+ bool Describe(PP_Size* size, bool* is_always_opaque);
+ bool PaintImageData(PP_Resource image,
+ const PP_Point* top_left,
+ const PP_Rect* src_rect);
+ bool Scroll(const PP_Rect* clip_rect, const PP_Point* amount);
+ bool ReplaceContents(PP_Resource image);
+ int32_t Flush(const PP_CompletionCallback& callback);
+
+ bool ReadImageData(PP_Resource image, const PP_Point* top_left);
+
+ // Assciates this device with the given plugin instance. You can pass NULL to
+ // clear the existing device. Returns true on success. In this case, a
+ // repaint of the page will also be scheduled. Failure means that the device
+ // is already bound to a different instance, and nothing will happen.
+ bool BindToInstance(PluginInstance* new_instance);
+
+ // Paints the current backing store to the web page.
+ void Paint(WebKit::WebCanvas* canvas,
+ const gfx::Rect& plugin_rect,
+ const gfx::Rect& paint_rect);
+
+ // Notifications that the view has rendered the page and that it has been
+ // flushed to the screen. These messages are used to send Flush callbacks to
+ // the plugin. See
+ void ViewInitiatedPaint();
+ void ViewFlushedPaint();
+
+ ImageData* image_data() { return image_data_.get(); }
+
+ private:
+ // Tracks a call to flush that requires a callback.
+ class FlushCallbackData {
+ public:
+ FlushCallbackData() {
+ Clear();
+ }
+
+ FlushCallbackData(const PP_CompletionCallback& callback) {
+ Set(callback);
+ }
+
+ bool is_null() const { return !callback_.func; }
+
+ void Set(const PP_CompletionCallback& callback) {
+ callback_ = callback;
+ }
+
+ void Clear() {
+ callback_ = PP_MakeCompletionCallback(NULL, 0);
+ }
+
+ void Execute(int32_t result) {
+ PP_RunCompletionCallback(&callback_, result);
+ }
+
+ private:
+ PP_CompletionCallback callback_;
+ };
+
+ // Called internally to execute the different queued commands. The
+ // parameters to these functions will have already been validated. The last
+ // rect argument will be filled by each function with the area affected by
+ // the update that requires invalidation. If there were no pixels changed,
+ // this rect can be untouched.
+ void ExecutePaintImageData(ImageData* image,
+ int x, int y,
+ const gfx::Rect& src_rect,
+ gfx::Rect* invalidated_rect);
+ void ExecuteScroll(const gfx::Rect& clip, int dx, int dy,
+ gfx::Rect* invalidated_rect);
+ void ExecuteReplaceContents(ImageData* image,
+ gfx::Rect* invalidated_rect);
+
+ // Schedules the offscreen callback to be fired at a future time. This
+ // will add the given item to the offscreen_flush_callbacks_ vector.
+ void ScheduleOffscreenCallback(const FlushCallbackData& callback);
+
+ // Function scheduled to execute by ScheduleOffscreenCallback that actually
+ // issues the offscreen callbacks.
+ void ExecuteOffscreenCallback(FlushCallbackData data);
+
+ // Returns true if there is any type of flush callback pending.
+ bool HasPendingFlush() const;
+
+ scoped_refptr<ImageData> image_data_;
+
+ // Non-owning pointer to the plugin instance this context is currently bound
+ // to, if any. If the context is currently unbound, this will be NULL.
+ PluginInstance* bound_instance_;
+
+ // Keeps track of all drawing commands queued before a Flush call.
+ struct QueuedOperation;
+ typedef std::vector<QueuedOperation> OperationQueue;
+ OperationQueue queued_operations_;
+
+ // Indicates whether any changes have been flushed to the backing store.
+ // This is initially false and is set to true at the first Flush() call.
+ bool flushed_any_data_;
+
+ // The plugin can give us one "Flush" at a time. This flush will either be in
+ // the "unpainted" state (in which case unpainted_flush_callback_ will be
+ // non-NULL) or painted, in which case painted_flush_callback_ will be
+ // non-NULL). There can also be an offscreen callback which is handled
+ // separately (see offscreen_callback_pending_). Only one of these three
+ // things may be set at a time to enforce the "only one pending flush at a
+ // time" constraint.
+ //
+ // "Unpainted" ones are flush requests which have never been painted. These
+ // could have been done while the RenderView was already waiting for an ACK
+ // from a previous paint, so won't generate a new one yet.
+ //
+ // "Painted" ones are those flushes that have been painted by RenderView, but
+ // for which the ACK from the browser has not yet been received.
+ //
+ // When we get updates from a plugin with a callback, it is first added to
+ // the unpainted callbacks. When the renderer has initiated a paint, we'll
+ // move it to the painted callbacks list. When the renderer receives a flush,
+ // we'll execute the callback and remove it from the list.
+ FlushCallbackData unpainted_flush_callback_;
+ FlushCallbackData painted_flush_callback_;
+
+ // When doing offscreen flushes, we issue a task that issues the callback
+ // later. This is set when one of those tasks is pending so that we can
+ // enforce the "only one pending flush at a time" constraint in the API.
+ bool offscreen_flush_pending_;
+
+ // Set to true if the plugin declares that this device will always be opaque.
+ // This allows us to do more optimized painting in some cases.
+ bool is_always_opaque_;
+
+ DISALLOW_COPY_AND_ASSIGN(Graphics2D);
+};
+
+} // namespace pepper
+
+#endif // WEBKIT_GLUE_PLUGINS_PEPPER_GRAPHICS_2D_H_
diff --git a/webkit/glue/plugins/pepper_graphics_3d.cc b/webkit/glue/plugins/pepper_graphics_3d.cc
new file mode 100644
index 0000000..18e5cd1
--- /dev/null
+++ b/webkit/glue/plugins/pepper_graphics_3d.cc
@@ -0,0 +1,256 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/glue/plugins/pepper_graphics_3d.h"
+
+#include "gpu/command_buffer/common/command_buffer.h"
+#include "base/singleton.h"
+#include "base/thread_local.h"
+#include "third_party/ppapi/c/dev/ppb_graphics_3d_dev.h"
+#include "webkit/glue/plugins/pepper_plugin_instance.h"
+
+namespace pepper {
+
+namespace {
+
+struct CurrentContextTag {};
+typedef Singleton<base::ThreadLocalPointer<Graphics3D>,
+ DefaultSingletonTraits<base::ThreadLocalPointer<Graphics3D> >,
+ CurrentContextTag> CurrentContextKey;
+
+// Size of the transfer buffer.
+enum { kTransferBufferSize = 512 * 1024 };
+
+bool IsGraphics3D(PP_Resource resource) {
+ return !!Resource::GetAs<Graphics3D>(resource);
+}
+
+bool GetConfigs(int32_t* configs, int32_t config_size, int32_t* num_config) {
+ // TODO(neb): Implement me!
+ return false;
+}
+
+bool ChooseConfig(const int32_t* attrib_list, int32_t* configs,
+ int32_t config_size, int32_t* num_config) {
+ // TODO(neb): Implement me!
+ return false;
+}
+
+bool GetConfigAttrib(int32_t config, int32_t attribute, int32_t* value) {
+ // TODO(neb): Implement me!
+ return false;
+}
+
+const char* QueryString(int32_t name) {
+ switch (name) {
+ case EGL_CLIENT_APIS:
+ return "OpenGL_ES";
+ case EGL_EXTENSIONS:
+ return "";
+ case EGL_VENDOR:
+ return "Google";
+ case EGL_VERSION:
+ return "1.0 Google";
+ default:
+ return NULL;
+ }
+}
+
+PP_Resource CreateContext(PP_Instance instance_id, int32_t config,
+ int32_t share_context,
+ const int32_t* attrib_list) {
+ DCHECK_EQ(0, share_context);
+
+ PluginInstance* instance = PluginInstance::FromPPInstance(instance_id);
+ if (!instance) {
+ return 0;
+ }
+
+ scoped_refptr<Graphics3D> context(new Graphics3D(instance->module()));
+ if (!context->Init(instance_id, config, attrib_list)) {
+ return 0;
+ }
+
+ return context->GetReference();
+}
+
+void* GetProcAddress(const char* name) {
+ // TODO(neb): Implement me!
+ return NULL;
+}
+
+bool MakeCurrent(PP_Resource graphics3d) {
+ if (!graphics3d) {
+ Graphics3D::ResetCurrent();
+ return true;
+ } else {
+ scoped_refptr<Graphics3D> context(Resource::GetAs<Graphics3D>(graphics3d));
+ return context.get() && context->MakeCurrent();
+ }
+}
+
+PP_Resource GetCurrentContext() {
+ Graphics3D* currentContext = Graphics3D::GetCurrent();
+ return currentContext ? currentContext->GetReference() : 0;
+}
+
+bool SwapBuffers(PP_Resource graphics3d) {
+ scoped_refptr<Graphics3D> context(Resource::GetAs<Graphics3D>(graphics3d));
+ return context && context->SwapBuffers();
+}
+
+uint32_t GetError() {
+ // TODO(neb): Figure out error checking.
+ return PP_GRAPHICS_3D_ERROR_SUCCESS;
+}
+
+const PPB_Graphics3D_Dev ppb_graphics3d = {
+ &IsGraphics3D,
+ &GetConfigs,
+ &ChooseConfig,
+ &GetConfigAttrib,
+ &QueryString,
+ &CreateContext,
+ &GetProcAddress,
+ &MakeCurrent,
+ &GetCurrentContext,
+ &SwapBuffers,
+ &GetError
+};
+
+} // namespace
+
+Graphics3D::Graphics3D(PluginModule* module)
+ : Resource(module),
+ command_buffer_(NULL),
+ transfer_buffer_id_(0),
+ method_factory3d_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+}
+
+const PPB_Graphics3D_Dev* Graphics3D::GetInterface() {
+ return &ppb_graphics3d;
+}
+
+Graphics3D* Graphics3D::GetCurrent() {
+ return CurrentContextKey::get()->Get();
+}
+
+void Graphics3D::ResetCurrent() {
+ CurrentContextKey::get()->Set(NULL);
+}
+
+Graphics3D::~Graphics3D() {
+ Destroy();
+}
+
+bool Graphics3D::Init(PP_Instance instance_id, int32_t config,
+ const int32_t* attrib_list) {
+ PluginInstance* instance = PluginInstance::FromPPInstance(instance_id);
+ if (!instance) {
+ return false;
+ }
+
+ // Create and initialize the objects required to issue GLES2 calls.
+ platform_context_.reset(instance->delegate()->CreateContext3D());
+ if (!platform_context_.get())
+ return false;
+
+ if (!platform_context_->Init(instance->position(),
+ instance->clip())) {
+ platform_context_.reset();
+ return false;
+ }
+ command_buffer_ = platform_context_->GetCommandBuffer();
+ gles2_helper_.reset(new gpu::gles2::GLES2CmdHelper(command_buffer_));
+ gpu::Buffer buffer = command_buffer_->GetRingBuffer();
+ if (gles2_helper_->Initialize(buffer.size)) {
+ transfer_buffer_id_ =
+ command_buffer_->CreateTransferBuffer(kTransferBufferSize);
+ gpu::Buffer transfer_buffer =
+ command_buffer_->GetTransferBuffer(transfer_buffer_id_);
+ if (transfer_buffer.ptr) {
+ gles2_implementation_.reset(new gpu::gles2::GLES2Implementation(
+ gles2_helper_.get(),
+ transfer_buffer.size,
+ transfer_buffer.ptr,
+ transfer_buffer_id_,
+ false));
+ platform_context_->SetNotifyRepaintTask(
+ method_factory3d_.NewRunnableMethod(&Graphics3D::HandleRepaint,
+ instance_id));
+ return true;
+ }
+ }
+
+ // Tear everything down if initialization failed.
+ Destroy();
+ return false;
+}
+
+bool Graphics3D::MakeCurrent() {
+ if (!command_buffer_)
+ return false;
+
+ CurrentContextKey::get()->Set(this);
+
+ // 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
+ // becuase making GL calls with a NULL context crashes.
+ // TODO(neb): Figure out error checking.
+// if (command_buffer_->GetCachedError() != gpu::error::kNoError)
+// return false;
+ return true;
+}
+
+bool Graphics3D::SwapBuffers() {
+ if (!command_buffer_)
+ return false;
+
+ // Don't request latest error status from service. Just use the locally cached
+ // information from the last flush.
+ // TODO(neb): Figure out error checking.
+// if (command_buffer_->GetCachedError() != gpu::error::kNoError)
+// return false;
+
+ gles2_implementation_->SwapBuffers();
+ return true;
+}
+
+void Graphics3D::Destroy() {
+ if (GetCurrent() == this) {
+ ResetCurrent();
+ }
+
+ method_factory3d_.RevokeAll();
+
+ gles2_implementation_.reset();
+
+ if (command_buffer_ && transfer_buffer_id_ != 0) {
+ command_buffer_->DestroyTransferBuffer(transfer_buffer_id_);
+ transfer_buffer_id_ = 0;
+ }
+
+ gles2_helper_.reset();
+
+ // Platform context owns the command buffer.
+ platform_context_.reset();
+ command_buffer_ = NULL;
+}
+
+void Graphics3D::HandleRepaint(PP_Instance instance_id) {
+ PluginInstance* instance = PluginInstance::FromPPInstance(instance_id);
+ if (instance) {
+ instance->Graphics3DContextLost();
+ if (platform_context_.get()) {
+ platform_context_->SetNotifyRepaintTask(
+ method_factory3d_.NewRunnableMethod(&Graphics3D::HandleRepaint,
+ instance_id));
+ }
+ }
+}
+
+} // namespace pepper
+
diff --git a/webkit/glue/plugins/pepper_graphics_3d.h b/webkit/glue/plugins/pepper_graphics_3d.h
new file mode 100644
index 0000000..16258ed
--- /dev/null
+++ b/webkit/glue/plugins/pepper_graphics_3d.h
@@ -0,0 +1,85 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_GLUE_PLUGINS_PEPPER_GRAPHICS_3D_H_
+#define WEBKIT_GLUE_PLUGINS_PEPPER_GRAPHICS_3D_H_
+
+#include "base/scoped_ptr.h"
+#include "gpu/command_buffer/client/gles2_cmd_helper.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "third_party/ppapi/c/pp_instance.h"
+#include "webkit/glue/plugins/pepper_plugin_delegate.h"
+#include "webkit/glue/plugins/pepper_resource.h"
+
+namespace gfx {
+class Rect;
+} // namespace gfx
+
+namespace gpu {
+class CommandBuffer;
+} // namespace gpu
+
+struct PPB_Graphics3D_Dev;
+struct PPB_OpenGLES_Dev;
+
+namespace pepper {
+
+class Graphics3D : public Resource {
+ public:
+ explicit Graphics3D(PluginModule* module);
+
+ virtual ~Graphics3D();
+
+ static const PPB_Graphics3D_Dev* GetInterface();
+ static const PPB_OpenGLES_Dev* GetOpenGLESInterface();
+
+ static bool Shutdown();
+
+ static Graphics3D* GetCurrent();
+
+ static void ResetCurrent();
+
+ // Resource override.
+ virtual Graphics3D* AsGraphics3D() {
+ return this;
+ }
+
+ bool Init(PP_Instance instance_id, int32_t config,
+ const int32_t* attrib_list);
+
+ bool MakeCurrent();
+
+ bool SwapBuffers();
+
+ gpu::gles2::GLES2Implementation* impl() {
+ return gles2_implementation_.get();
+ }
+
+ private:
+ void HandleRepaint(PP_Instance instance_id);
+ void Destroy();
+
+ // PluginDelegate's 3D Context. Responsible for providing the command buffer.
+ scoped_ptr<PluginDelegate::PlatformContext3D> platform_context_;
+
+ // Command buffer is owned by the platform context.
+ gpu::CommandBuffer* command_buffer_;
+
+ // GLES2 Command Helper instance.
+ scoped_ptr<gpu::gles2::GLES2CmdHelper> gles2_helper_;
+
+ // ID of the transfer buffer.
+ int32_t transfer_buffer_id_;
+
+ // GLES2 Implementation instance.
+ scoped_ptr<gpu::gles2::GLES2Implementation> gles2_implementation_;
+
+ // Runnable methods that must be cancelled when the 3D context is destroyed.
+ ScopedRunnableMethodFactory<Graphics3D> method_factory3d_;
+};
+
+} // namespace pepper
+
+#endif // WEBKIT_GLUE_PLUGINS_PEPPER_GRAPHICS_3D_H_
+
diff --git a/webkit/glue/plugins/pepper_graphics_3d_gl.cc b/webkit/glue/plugins/pepper_graphics_3d_gl.cc
new file mode 100644
index 0000000..897e459
--- /dev/null
+++ b/webkit/glue/plugins/pepper_graphics_3d_gl.cc
@@ -0,0 +1,716 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is auto-generated. DO NOT EDIT!
+
+#include "webkit/glue/plugins/pepper_graphics_3d.h"
+
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "third_party/ppapi/c/dev/ppb_opengles_dev.h"
+
+namespace pepper {
+
+namespace {
+
+void ActiveTexture(GLenum texture) {
+ Graphics3D::GetCurrent()->impl()->ActiveTexture(texture);
+}
+void AttachShader(GLuint program, GLuint shader) {
+ Graphics3D::GetCurrent()->impl()->AttachShader(program, shader);
+}
+void BindAttribLocation(GLuint program, GLuint index, const char* name) {
+ Graphics3D::GetCurrent()->impl()->BindAttribLocation(program, index, name);
+}
+void BindBuffer(GLenum target, GLuint buffer) {
+ Graphics3D::GetCurrent()->impl()->BindBuffer(target, buffer);
+}
+void BindFramebuffer(GLenum target, GLuint framebuffer) {
+ Graphics3D::GetCurrent()->impl()->BindFramebuffer(target, framebuffer);
+}
+void BindRenderbuffer(GLenum target, GLuint renderbuffer) {
+ Graphics3D::GetCurrent()->impl()->BindRenderbuffer(target, renderbuffer);
+}
+void BindTexture(GLenum target, GLuint texture) {
+ Graphics3D::GetCurrent()->impl()->BindTexture(target, texture);
+}
+void BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
+ Graphics3D::GetCurrent()->impl()->BlendColor(red, green, blue, alpha);
+}
+void BlendEquation(GLenum mode) {
+ Graphics3D::GetCurrent()->impl()->BlendEquation(mode);
+}
+void BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) {
+ Graphics3D::GetCurrent()->impl()->BlendEquationSeparate(modeRGB, modeAlpha);
+}
+void BlendFunc(GLenum sfactor, GLenum dfactor) {
+ Graphics3D::GetCurrent()->impl()->BlendFunc(sfactor, dfactor);
+}
+void BlendFuncSeparate(
+ GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
+ Graphics3D::GetCurrent()->impl()->BlendFuncSeparate(
+ srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+void BufferData(
+ GLenum target, GLsizeiptr size, const void* data, GLenum usage) {
+ Graphics3D::GetCurrent()->impl()->BufferData(target, size, data, usage);
+}
+void BufferSubData(
+ GLenum target, GLintptr offset, GLsizeiptr size, const void* data) {
+ Graphics3D::GetCurrent()->impl()->BufferSubData(target, offset, size, data);
+}
+GLenum CheckFramebufferStatus(GLenum target) {
+ return Graphics3D::GetCurrent()->impl()->CheckFramebufferStatus(target);
+}
+void Clear(GLbitfield mask) {
+ Graphics3D::GetCurrent()->impl()->Clear(mask);
+}
+void ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
+ Graphics3D::GetCurrent()->impl()->ClearColor(red, green, blue, alpha);
+}
+void ClearDepthf(GLclampf depth) {
+ Graphics3D::GetCurrent()->impl()->ClearDepthf(depth);
+}
+void ClearStencil(GLint s) {
+ Graphics3D::GetCurrent()->impl()->ClearStencil(s);
+}
+void ColorMask(
+ GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
+ Graphics3D::GetCurrent()->impl()->ColorMask(red, green, blue, alpha);
+}
+void CompileShader(GLuint shader) {
+ Graphics3D::GetCurrent()->impl()->CompileShader(shader);
+}
+void CompressedTexImage2D(
+ GLenum target, GLint level, GLenum internalformat, GLsizei width,
+ GLsizei height, GLint border, GLsizei imageSize, const void* data) {
+ Graphics3D::GetCurrent()->impl()->CompressedTexImage2D(
+ target, level, internalformat, width, height, border, imageSize, data);
+}
+void CompressedTexSubImage2D(
+ GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
+ GLsizei height, GLenum format, GLsizei imageSize, const void* data) {
+ Graphics3D::GetCurrent()->impl()->CompressedTexSubImage2D(
+ target, level, xoffset, yoffset, width, height, format, imageSize, data);
+}
+void CopyTexImage2D(
+ GLenum target, GLint level, GLenum internalformat, GLint x, GLint y,
+ GLsizei width, GLsizei height, GLint border) {
+ Graphics3D::GetCurrent()->impl()->CopyTexImage2D(
+ target, level, internalformat, x, y, width, height, border);
+}
+void CopyTexSubImage2D(
+ GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y,
+ GLsizei width, GLsizei height) {
+ Graphics3D::GetCurrent()->impl()->CopyTexSubImage2D(
+ target, level, xoffset, yoffset, x, y, width, height);
+}
+GLuint CreateProgram() {
+ return Graphics3D::GetCurrent()->impl()->CreateProgram();
+}
+GLuint CreateShader(GLenum type) {
+ return Graphics3D::GetCurrent()->impl()->CreateShader(type);
+}
+void CullFace(GLenum mode) {
+ Graphics3D::GetCurrent()->impl()->CullFace(mode);
+}
+void DeleteBuffers(GLsizei n, const GLuint* buffers) {
+ Graphics3D::GetCurrent()->impl()->DeleteBuffers(n, buffers);
+}
+void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers) {
+ Graphics3D::GetCurrent()->impl()->DeleteFramebuffers(n, framebuffers);
+}
+void DeleteProgram(GLuint program) {
+ Graphics3D::GetCurrent()->impl()->DeleteProgram(program);
+}
+void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) {
+ Graphics3D::GetCurrent()->impl()->DeleteRenderbuffers(n, renderbuffers);
+}
+void DeleteShader(GLuint shader) {
+ Graphics3D::GetCurrent()->impl()->DeleteShader(shader);
+}
+void DeleteTextures(GLsizei n, const GLuint* textures) {
+ Graphics3D::GetCurrent()->impl()->DeleteTextures(n, textures);
+}
+void DepthFunc(GLenum func) {
+ Graphics3D::GetCurrent()->impl()->DepthFunc(func);
+}
+void DepthMask(GLboolean flag) {
+ Graphics3D::GetCurrent()->impl()->DepthMask(flag);
+}
+void DepthRangef(GLclampf zNear, GLclampf zFar) {
+ Graphics3D::GetCurrent()->impl()->DepthRangef(zNear, zFar);
+}
+void DetachShader(GLuint program, GLuint shader) {
+ Graphics3D::GetCurrent()->impl()->DetachShader(program, shader);
+}
+void Disable(GLenum cap) {
+ Graphics3D::GetCurrent()->impl()->Disable(cap);
+}
+void DisableVertexAttribArray(GLuint index) {
+ Graphics3D::GetCurrent()->impl()->DisableVertexAttribArray(index);
+}
+void DrawArrays(GLenum mode, GLint first, GLsizei count) {
+ Graphics3D::GetCurrent()->impl()->DrawArrays(mode, first, count);
+}
+void DrawElements(
+ GLenum mode, GLsizei count, GLenum type, const void* indices) {
+ Graphics3D::GetCurrent()->impl()->DrawElements(mode, count, type, indices);
+}
+void Enable(GLenum cap) {
+ Graphics3D::GetCurrent()->impl()->Enable(cap);
+}
+void EnableVertexAttribArray(GLuint index) {
+ Graphics3D::GetCurrent()->impl()->EnableVertexAttribArray(index);
+}
+void Finish() {
+ Graphics3D::GetCurrent()->impl()->Finish();
+}
+void Flush() {
+ Graphics3D::GetCurrent()->impl()->Flush();
+}
+void FramebufferRenderbuffer(
+ GLenum target, GLenum attachment, GLenum renderbuffertarget,
+ GLuint renderbuffer) {
+ Graphics3D::GetCurrent()->impl()->FramebufferRenderbuffer(
+ target, attachment, renderbuffertarget, renderbuffer);
+}
+void FramebufferTexture2D(
+ GLenum target, GLenum attachment, GLenum textarget, GLuint texture,
+ GLint level) {
+ Graphics3D::GetCurrent()->impl()->FramebufferTexture2D(
+ target, attachment, textarget, texture, level);
+}
+void FrontFace(GLenum mode) {
+ Graphics3D::GetCurrent()->impl()->FrontFace(mode);
+}
+void GenBuffers(GLsizei n, GLuint* buffers) {
+ Graphics3D::GetCurrent()->impl()->GenBuffers(n, buffers);
+}
+void GenerateMipmap(GLenum target) {
+ Graphics3D::GetCurrent()->impl()->GenerateMipmap(target);
+}
+void GenFramebuffers(GLsizei n, GLuint* framebuffers) {
+ Graphics3D::GetCurrent()->impl()->GenFramebuffers(n, framebuffers);
+}
+void GenRenderbuffers(GLsizei n, GLuint* renderbuffers) {
+ Graphics3D::GetCurrent()->impl()->GenRenderbuffers(n, renderbuffers);
+}
+void GenTextures(GLsizei n, GLuint* textures) {
+ Graphics3D::GetCurrent()->impl()->GenTextures(n, textures);
+}
+void GetActiveAttrib(
+ GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size,
+ GLenum* type, char* name) {
+ Graphics3D::GetCurrent()->impl()->GetActiveAttrib(
+ program, index, bufsize, length, size, type, name);
+}
+void GetActiveUniform(
+ GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size,
+ GLenum* type, char* name) {
+ Graphics3D::GetCurrent()->impl()->GetActiveUniform(
+ program, index, bufsize, length, size, type, name);
+}
+void GetAttachedShaders(
+ GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) {
+ Graphics3D::GetCurrent()->impl()->GetAttachedShaders(
+ program, maxcount, count, shaders);
+}
+GLint GetAttribLocation(GLuint program, const char* name) {
+ return Graphics3D::GetCurrent()->impl()->GetAttribLocation(program, name);
+}
+void GetBooleanv(GLenum pname, GLboolean* params) {
+ Graphics3D::GetCurrent()->impl()->GetBooleanv(pname, params);
+}
+void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params) {
+ Graphics3D::GetCurrent()->impl()->GetBufferParameteriv(
+ target, pname, params);
+}
+GLenum GetError() {
+ return Graphics3D::GetCurrent()->impl()->GetError();
+}
+void GetFloatv(GLenum pname, GLfloat* params) {
+ Graphics3D::GetCurrent()->impl()->GetFloatv(pname, params);
+}
+void GetFramebufferAttachmentParameteriv(
+ GLenum target, GLenum attachment, GLenum pname, GLint* params) {
+ Graphics3D::GetCurrent()->impl()->GetFramebufferAttachmentParameteriv(
+ target, attachment, pname, params);
+}
+void GetIntegerv(GLenum pname, GLint* params) {
+ Graphics3D::GetCurrent()->impl()->GetIntegerv(pname, params);
+}
+void GetProgramiv(GLuint program, GLenum pname, GLint* params) {
+ Graphics3D::GetCurrent()->impl()->GetProgramiv(program, pname, params);
+}
+void GetProgramInfoLog(
+ GLuint program, GLsizei bufsize, GLsizei* length, char* infolog) {
+ Graphics3D::GetCurrent()->impl()->GetProgramInfoLog(
+ program, bufsize, length, infolog);
+}
+void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) {
+ Graphics3D::GetCurrent()->impl()->GetRenderbufferParameteriv(
+ target, pname, params);
+}
+void GetShaderiv(GLuint shader, GLenum pname, GLint* params) {
+ Graphics3D::GetCurrent()->impl()->GetShaderiv(shader, pname, params);
+}
+void GetShaderInfoLog(
+ GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog) {
+ Graphics3D::GetCurrent()->impl()->GetShaderInfoLog(
+ shader, bufsize, length, infolog);
+}
+void GetShaderPrecisionFormat(
+ GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
+ Graphics3D::GetCurrent()->impl()->GetShaderPrecisionFormat(
+ shadertype, precisiontype, range, precision);
+}
+void GetShaderSource(
+ GLuint shader, GLsizei bufsize, GLsizei* length, char* source) {
+ Graphics3D::GetCurrent()->impl()->GetShaderSource(
+ shader, bufsize, length, source);
+}
+const GLubyte* GetString(GLenum name) {
+ return Graphics3D::GetCurrent()->impl()->GetString(name);
+}
+void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) {
+ Graphics3D::GetCurrent()->impl()->GetTexParameterfv(target, pname, params);
+}
+void GetTexParameteriv(GLenum target, GLenum pname, GLint* params) {
+ Graphics3D::GetCurrent()->impl()->GetTexParameteriv(target, pname, params);
+}
+void GetUniformfv(GLuint program, GLint location, GLfloat* params) {
+ Graphics3D::GetCurrent()->impl()->GetUniformfv(program, location, params);
+}
+void GetUniformiv(GLuint program, GLint location, GLint* params) {
+ Graphics3D::GetCurrent()->impl()->GetUniformiv(program, location, params);
+}
+GLint GetUniformLocation(GLuint program, const char* name) {
+ return Graphics3D::GetCurrent()->impl()->GetUniformLocation(program, name);
+}
+void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) {
+ Graphics3D::GetCurrent()->impl()->GetVertexAttribfv(index, pname, params);
+}
+void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params) {
+ Graphics3D::GetCurrent()->impl()->GetVertexAttribiv(index, pname, params);
+}
+void GetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer) {
+ Graphics3D::GetCurrent()->impl()->GetVertexAttribPointerv(
+ index, pname, pointer);
+}
+void Hint(GLenum target, GLenum mode) {
+ Graphics3D::GetCurrent()->impl()->Hint(target, mode);
+}
+GLboolean IsBuffer(GLuint buffer) {
+ return Graphics3D::GetCurrent()->impl()->IsBuffer(buffer);
+}
+GLboolean IsEnabled(GLenum cap) {
+ return Graphics3D::GetCurrent()->impl()->IsEnabled(cap);
+}
+GLboolean IsFramebuffer(GLuint framebuffer) {
+ return Graphics3D::GetCurrent()->impl()->IsFramebuffer(framebuffer);
+}
+GLboolean IsProgram(GLuint program) {
+ return Graphics3D::GetCurrent()->impl()->IsProgram(program);
+}
+GLboolean IsRenderbuffer(GLuint renderbuffer) {
+ return Graphics3D::GetCurrent()->impl()->IsRenderbuffer(renderbuffer);
+}
+GLboolean IsShader(GLuint shader) {
+ return Graphics3D::GetCurrent()->impl()->IsShader(shader);
+}
+GLboolean IsTexture(GLuint texture) {
+ return Graphics3D::GetCurrent()->impl()->IsTexture(texture);
+}
+void LineWidth(GLfloat width) {
+ Graphics3D::GetCurrent()->impl()->LineWidth(width);
+}
+void LinkProgram(GLuint program) {
+ Graphics3D::GetCurrent()->impl()->LinkProgram(program);
+}
+void PixelStorei(GLenum pname, GLint param) {
+ Graphics3D::GetCurrent()->impl()->PixelStorei(pname, param);
+}
+void PolygonOffset(GLfloat factor, GLfloat units) {
+ Graphics3D::GetCurrent()->impl()->PolygonOffset(factor, units);
+}
+void ReadPixels(
+ GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
+ void* pixels) {
+ Graphics3D::GetCurrent()->impl()->ReadPixels(
+ x, y, width, height, format, type, pixels);
+}
+void ReleaseShaderCompiler() {
+ Graphics3D::GetCurrent()->impl()->ReleaseShaderCompiler();
+}
+void RenderbufferStorage(
+ GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
+ Graphics3D::GetCurrent()->impl()->RenderbufferStorage(
+ target, internalformat, width, height);
+}
+void SampleCoverage(GLclampf value, GLboolean invert) {
+ Graphics3D::GetCurrent()->impl()->SampleCoverage(value, invert);
+}
+void Scissor(GLint x, GLint y, GLsizei width, GLsizei height) {
+ Graphics3D::GetCurrent()->impl()->Scissor(x, y, width, height);
+}
+void ShaderBinary(
+ GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary,
+ GLsizei length) {
+ Graphics3D::GetCurrent()->impl()->ShaderBinary(
+ n, shaders, binaryformat, binary, length);
+}
+void ShaderSource(
+ GLuint shader, GLsizei count, const char** str, const GLint* length) {
+ Graphics3D::GetCurrent()->impl()->ShaderSource(shader, count, str, length);
+}
+void StencilFunc(GLenum func, GLint ref, GLuint mask) {
+ Graphics3D::GetCurrent()->impl()->StencilFunc(func, ref, mask);
+}
+void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) {
+ Graphics3D::GetCurrent()->impl()->StencilFuncSeparate(face, func, ref, mask);
+}
+void StencilMask(GLuint mask) {
+ Graphics3D::GetCurrent()->impl()->StencilMask(mask);
+}
+void StencilMaskSeparate(GLenum face, GLuint mask) {
+ Graphics3D::GetCurrent()->impl()->StencilMaskSeparate(face, mask);
+}
+void StencilOp(GLenum fail, GLenum zfail, GLenum zpass) {
+ Graphics3D::GetCurrent()->impl()->StencilOp(fail, zfail, zpass);
+}
+void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) {
+ Graphics3D::GetCurrent()->impl()->StencilOpSeparate(
+ face, fail, zfail, zpass);
+}
+void TexImage2D(
+ GLenum target, GLint level, GLint internalformat, GLsizei width,
+ GLsizei height, GLint border, GLenum format, GLenum type,
+ const void* pixels) {
+ Graphics3D::GetCurrent()->impl()->TexImage2D(
+ target, level, internalformat, width, height, border, format, type,
+ pixels);
+}
+void TexParameterf(GLenum target, GLenum pname, GLfloat param) {
+ Graphics3D::GetCurrent()->impl()->TexParameterf(target, pname, param);
+}
+void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params) {
+ Graphics3D::GetCurrent()->impl()->TexParameterfv(target, pname, params);
+}
+void TexParameteri(GLenum target, GLenum pname, GLint param) {
+ Graphics3D::GetCurrent()->impl()->TexParameteri(target, pname, param);
+}
+void TexParameteriv(GLenum target, GLenum pname, const GLint* params) {
+ Graphics3D::GetCurrent()->impl()->TexParameteriv(target, pname, params);
+}
+void TexSubImage2D(
+ GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
+ GLsizei height, GLenum format, GLenum type, const void* pixels) {
+ Graphics3D::GetCurrent()->impl()->TexSubImage2D(
+ target, level, xoffset, yoffset, width, height, format, type, pixels);
+}
+void Uniform1f(GLint location, GLfloat x) {
+ Graphics3D::GetCurrent()->impl()->Uniform1f(location, x);
+}
+void Uniform1fv(GLint location, GLsizei count, const GLfloat* v) {
+ Graphics3D::GetCurrent()->impl()->Uniform1fv(location, count, v);
+}
+void Uniform1i(GLint location, GLint x) {
+ Graphics3D::GetCurrent()->impl()->Uniform1i(location, x);
+}
+void Uniform1iv(GLint location, GLsizei count, const GLint* v) {
+ Graphics3D::GetCurrent()->impl()->Uniform1iv(location, count, v);
+}
+void Uniform2f(GLint location, GLfloat x, GLfloat y) {
+ Graphics3D::GetCurrent()->impl()->Uniform2f(location, x, y);
+}
+void Uniform2fv(GLint location, GLsizei count, const GLfloat* v) {
+ Graphics3D::GetCurrent()->impl()->Uniform2fv(location, count, v);
+}
+void Uniform2i(GLint location, GLint x, GLint y) {
+ Graphics3D::GetCurrent()->impl()->Uniform2i(location, x, y);
+}
+void Uniform2iv(GLint location, GLsizei count, const GLint* v) {
+ Graphics3D::GetCurrent()->impl()->Uniform2iv(location, count, v);
+}
+void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) {
+ Graphics3D::GetCurrent()->impl()->Uniform3f(location, x, y, z);
+}
+void Uniform3fv(GLint location, GLsizei count, const GLfloat* v) {
+ Graphics3D::GetCurrent()->impl()->Uniform3fv(location, count, v);
+}
+void Uniform3i(GLint location, GLint x, GLint y, GLint z) {
+ Graphics3D::GetCurrent()->impl()->Uniform3i(location, x, y, z);
+}
+void Uniform3iv(GLint location, GLsizei count, const GLint* v) {
+ Graphics3D::GetCurrent()->impl()->Uniform3iv(location, count, v);
+}
+void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
+ Graphics3D::GetCurrent()->impl()->Uniform4f(location, x, y, z, w);
+}
+void Uniform4fv(GLint location, GLsizei count, const GLfloat* v) {
+ Graphics3D::GetCurrent()->impl()->Uniform4fv(location, count, v);
+}
+void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) {
+ Graphics3D::GetCurrent()->impl()->Uniform4i(location, x, y, z, w);
+}
+void Uniform4iv(GLint location, GLsizei count, const GLint* v) {
+ Graphics3D::GetCurrent()->impl()->Uniform4iv(location, count, v);
+}
+void UniformMatrix2fv(
+ GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
+ Graphics3D::GetCurrent()->impl()->UniformMatrix2fv(
+ location, count, transpose, value);
+}
+void UniformMatrix3fv(
+ GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
+ Graphics3D::GetCurrent()->impl()->UniformMatrix3fv(
+ location, count, transpose, value);
+}
+void UniformMatrix4fv(
+ GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
+ Graphics3D::GetCurrent()->impl()->UniformMatrix4fv(
+ location, count, transpose, value);
+}
+void UseProgram(GLuint program) {
+ Graphics3D::GetCurrent()->impl()->UseProgram(program);
+}
+void ValidateProgram(GLuint program) {
+ Graphics3D::GetCurrent()->impl()->ValidateProgram(program);
+}
+void VertexAttrib1f(GLuint indx, GLfloat x) {
+ Graphics3D::GetCurrent()->impl()->VertexAttrib1f(indx, x);
+}
+void VertexAttrib1fv(GLuint indx, const GLfloat* values) {
+ Graphics3D::GetCurrent()->impl()->VertexAttrib1fv(indx, values);
+}
+void VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) {
+ Graphics3D::GetCurrent()->impl()->VertexAttrib2f(indx, x, y);
+}
+void VertexAttrib2fv(GLuint indx, const GLfloat* values) {
+ Graphics3D::GetCurrent()->impl()->VertexAttrib2fv(indx, values);
+}
+void VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) {
+ Graphics3D::GetCurrent()->impl()->VertexAttrib3f(indx, x, y, z);
+}
+void VertexAttrib3fv(GLuint indx, const GLfloat* values) {
+ Graphics3D::GetCurrent()->impl()->VertexAttrib3fv(indx, values);
+}
+void VertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
+ Graphics3D::GetCurrent()->impl()->VertexAttrib4f(indx, x, y, z, w);
+}
+void VertexAttrib4fv(GLuint indx, const GLfloat* values) {
+ Graphics3D::GetCurrent()->impl()->VertexAttrib4fv(indx, values);
+}
+void VertexAttribPointer(
+ GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride,
+ const void* ptr) {
+ Graphics3D::GetCurrent()->impl()->VertexAttribPointer(
+ indx, size, type, normalized, stride, ptr);
+}
+void Viewport(GLint x, GLint y, GLsizei width, GLsizei height) {
+ Graphics3D::GetCurrent()->impl()->Viewport(x, y, width, height);
+}
+void SwapBuffers() {
+ Graphics3D::GetCurrent()->impl()->SwapBuffers();
+}
+GLuint GetMaxValueInBuffer(
+ GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
+ return Graphics3D::GetCurrent()->impl()->GetMaxValueInBuffer(
+ buffer_id, count, type, offset);
+}
+void GenSharedIds(
+ GLuint namespace_id, GLuint id_offset, GLsizei n, GLuint* ids) {
+ Graphics3D::GetCurrent()->impl()->GenSharedIds(
+ namespace_id, id_offset, n, ids);
+}
+void DeleteSharedIds(GLuint namespace_id, GLsizei n, const GLuint* ids) {
+ Graphics3D::GetCurrent()->impl()->DeleteSharedIds(namespace_id, n, ids);
+}
+void RegisterSharedIds(GLuint namespace_id, GLsizei n, const GLuint* ids) {
+ Graphics3D::GetCurrent()->impl()->RegisterSharedIds(namespace_id, n, ids);
+}
+GLboolean CommandBufferEnable(const char* feature) {
+ return Graphics3D::GetCurrent()->impl()->CommandBufferEnable(feature);
+}
+void* MapBufferSubData(
+ GLuint target, GLintptr offset, GLsizeiptr size, GLenum access) {
+ return Graphics3D::GetCurrent()->impl()->MapBufferSubData(
+ target, offset, size, access);
+}
+void UnmapBufferSubData(const void* mem) {
+ Graphics3D::GetCurrent()->impl()->UnmapBufferSubData(mem);
+}
+void* MapTexSubImage2D(
+ GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
+ GLsizei height, GLenum format, GLenum type, GLenum access) {
+ return Graphics3D::GetCurrent()->impl()->MapTexSubImage2D(
+ target, level, xoffset, yoffset, width, height, format, type, access);
+}
+void UnmapTexSubImage2D(const void* mem) {
+ Graphics3D::GetCurrent()->impl()->UnmapTexSubImage2D(mem);
+}
+
+const PPB_OpenGLES_Dev ppb_opengles = {
+ &ActiveTexture,
+ &AttachShader,
+ &BindAttribLocation,
+ &BindBuffer,
+ &BindFramebuffer,
+ &BindRenderbuffer,
+ &BindTexture,
+ &BlendColor,
+ &BlendEquation,
+ &BlendEquationSeparate,
+ &BlendFunc,
+ &BlendFuncSeparate,
+ &BufferData,
+ &BufferSubData,
+ &CheckFramebufferStatus,
+ &Clear,
+ &ClearColor,
+ &ClearDepthf,
+ &ClearStencil,
+ &ColorMask,
+ &CompileShader,
+ &CompressedTexImage2D,
+ &CompressedTexSubImage2D,
+ &CopyTexImage2D,
+ &CopyTexSubImage2D,
+ &CreateProgram,
+ &CreateShader,
+ &CullFace,
+ &DeleteBuffers,
+ &DeleteFramebuffers,
+ &DeleteProgram,
+ &DeleteRenderbuffers,
+ &DeleteShader,
+ &DeleteTextures,
+ &DepthFunc,
+ &DepthMask,
+ &DepthRangef,
+ &DetachShader,
+ &Disable,
+ &DisableVertexAttribArray,
+ &DrawArrays,
+ &DrawElements,
+ &Enable,
+ &EnableVertexAttribArray,
+ &Finish,
+ &Flush,
+ &FramebufferRenderbuffer,
+ &FramebufferTexture2D,
+ &FrontFace,
+ &GenBuffers,
+ &GenerateMipmap,
+ &GenFramebuffers,
+ &GenRenderbuffers,
+ &GenTextures,
+ &GetActiveAttrib,
+ &GetActiveUniform,
+ &GetAttachedShaders,
+ &GetAttribLocation,
+ &GetBooleanv,
+ &GetBufferParameteriv,
+ &GetError,
+ &GetFloatv,
+ &GetFramebufferAttachmentParameteriv,
+ &GetIntegerv,
+ &GetProgramiv,
+ &GetProgramInfoLog,
+ &GetRenderbufferParameteriv,
+ &GetShaderiv,
+ &GetShaderInfoLog,
+ &GetShaderPrecisionFormat,
+ &GetShaderSource,
+ &GetString,
+ &GetTexParameterfv,
+ &GetTexParameteriv,
+ &GetUniformfv,
+ &GetUniformiv,
+ &GetUniformLocation,
+ &GetVertexAttribfv,
+ &GetVertexAttribiv,
+ &GetVertexAttribPointerv,
+ &Hint,
+ &IsBuffer,
+ &IsEnabled,
+ &IsFramebuffer,
+ &IsProgram,
+ &IsRenderbuffer,
+ &IsShader,
+ &IsTexture,
+ &LineWidth,
+ &LinkProgram,
+ &PixelStorei,
+ &PolygonOffset,
+ &ReadPixels,
+ &ReleaseShaderCompiler,
+ &RenderbufferStorage,
+ &SampleCoverage,
+ &Scissor,
+ &ShaderBinary,
+ &ShaderSource,
+ &StencilFunc,
+ &StencilFuncSeparate,
+ &StencilMask,
+ &StencilMaskSeparate,
+ &StencilOp,
+ &StencilOpSeparate,
+ &TexImage2D,
+ &TexParameterf,
+ &TexParameterfv,
+ &TexParameteri,
+ &TexParameteriv,
+ &TexSubImage2D,
+ &Uniform1f,
+ &Uniform1fv,
+ &Uniform1i,
+ &Uniform1iv,
+ &Uniform2f,
+ &Uniform2fv,
+ &Uniform2i,
+ &Uniform2iv,
+ &Uniform3f,
+ &Uniform3fv,
+ &Uniform3i,
+ &Uniform3iv,
+ &Uniform4f,
+ &Uniform4fv,
+ &Uniform4i,
+ &Uniform4iv,
+ &UniformMatrix2fv,
+ &UniformMatrix3fv,
+ &UniformMatrix4fv,
+ &UseProgram,
+ &ValidateProgram,
+ &VertexAttrib1f,
+ &VertexAttrib1fv,
+ &VertexAttrib2f,
+ &VertexAttrib2fv,
+ &VertexAttrib3f,
+ &VertexAttrib3fv,
+ &VertexAttrib4f,
+ &VertexAttrib4fv,
+ &VertexAttribPointer,
+ &Viewport,
+ &SwapBuffers,
+ &GetMaxValueInBuffer,
+ &GenSharedIds,
+ &DeleteSharedIds,
+ &RegisterSharedIds,
+ &CommandBufferEnable,
+ &MapBufferSubData,
+ &UnmapBufferSubData,
+ &MapTexSubImage2D,
+ &UnmapTexSubImage2D
+};
+
+} // namespace
+
+const PPB_OpenGLES_Dev* Graphics3D::GetOpenGLESInterface() {
+ return &ppb_opengles;
+}
+
+} // namespace pepper
+
diff --git a/webkit/glue/plugins/pepper_plugin_object.cc b/webkit/glue/plugins/pepper_plugin_object.cc
new file mode 100644
index 0000000..c0a7cd6
--- /dev/null
+++ b/webkit/glue/plugins/pepper_plugin_object.cc
@@ -0,0 +1,601 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/glue/plugins/pepper_plugin_object.h"
+
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "base/string_number_conversions.h"
+#include "base/string_util.h"
+#include "third_party/npapi/bindings/npapi.h"
+#include "third_party/npapi/bindings/npruntime.h"
+#include "third_party/ppapi/c/pp_var.h"
+#include "third_party/ppapi/c/ppb_var.h"
+#include "third_party/ppapi/c/ppp_class.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebBindings.h"
+#include "webkit/glue/plugins/pepper_plugin_module.h"
+#include "webkit/glue/plugins/pepper_string.h"
+#include "webkit/glue/plugins/pepper_var.h"
+
+using WebKit::WebBindings;
+
+namespace pepper {
+
+namespace {
+
+const char kInvalidValueException[] = "Error: Invalid value";
+const char kInvalidPluginValue[] = "Error: Plugin returned invalid value.";
+
+// ---------------------------------------------------------------------------
+// Utilities
+
+// Converts the given PP_Var to an NPVariant, returning true on success.
+// False means that the given variant is invalid. In this case, the result
+// NPVariant will be set to a void one.
+//
+// The contents of the PP_Var will be copied unless the PP_Var corresponds to
+// an object.
+bool PPVarToNPVariant(PP_Var var, NPVariant* result) {
+ switch (var.type) {
+ case PP_VARTYPE_VOID:
+ VOID_TO_NPVARIANT(*result);
+ break;
+ case PP_VARTYPE_NULL:
+ NULL_TO_NPVARIANT(*result);
+ break;
+ case PP_VARTYPE_BOOL:
+ BOOLEAN_TO_NPVARIANT(var.value.as_bool, *result);
+ break;
+ case PP_VARTYPE_INT32:
+ INT32_TO_NPVARIANT(var.value.as_int, *result);
+ break;
+ case PP_VARTYPE_DOUBLE:
+ DOUBLE_TO_NPVARIANT(var.value.as_double, *result);
+ break;
+ case PP_VARTYPE_STRING: {
+ scoped_refptr<StringVar> string(StringVar::FromPPVar(var));
+ if (!string) {
+ VOID_TO_NPVARIANT(*result);
+ return false;
+ }
+ const std::string& value = string->value();
+ STRINGN_TO_NPVARIANT(base::strdup(value.c_str()), value.size(), *result);
+ break;
+ }
+ case PP_VARTYPE_OBJECT: {
+ scoped_refptr<ObjectVar> object(ObjectVar::FromPPVar(var));
+ if (!object) {
+ VOID_TO_NPVARIANT(*result);
+ return false;
+ }
+ OBJECT_TO_NPVARIANT(WebBindings::retainObject(object->np_object()),
+ *result);
+ break;
+ }
+ }
+ return true;
+}
+
+// PPVarArrayFromNPVariantArray ------------------------------------------------
+
+// Converts an array of NPVariants to an array of PP_Var, and scopes the
+// ownership of the PP_Var. This is used when converting argument lists from
+// WebKit to the plugin.
+class PPVarArrayFromNPVariantArray {
+ public:
+ PPVarArrayFromNPVariantArray(PluginModule* module,
+ size_t size,
+ const NPVariant* variants)
+ : size_(size) {
+ if (size_ > 0) {
+ array_.reset(new PP_Var[size_]);
+ for (size_t i = 0; i < size_; i++)
+ array_[i] = Var::NPVariantToPPVar(module, &variants[i]);
+ }
+ }
+
+ ~PPVarArrayFromNPVariantArray() {
+ for (size_t i = 0; i < size_; i++)
+ Var::PluginReleasePPVar(array_[i]);
+ }
+
+ PP_Var* array() { return array_.get(); }
+
+ private:
+ size_t size_;
+ scoped_array<PP_Var> array_;
+
+ DISALLOW_COPY_AND_ASSIGN(PPVarArrayFromNPVariantArray);
+};
+
+// PPResultAndExceptionToNPResult ----------------------------------------------
+
+// Convenience object for converting a PPAPI call that can throw an exception
+// and optionally return a value, back to the NPAPI layer which expects a
+// NPVariant as a result.
+//
+// Normal usage is that you will pass the result of exception() to the
+// PPAPI function as the exception output parameter. Then you will either
+// call SetResult with the result of the PPAPI call, or
+// CheckExceptionForNoResult if the PPAPI call doesn't return a PP_Var.
+//
+// Both SetResult and CheckExceptionForNoResult will throw an exception to
+// the JavaScript library if the plugin reported an exception. SetResult
+// will additionally convert the result to an NPVariant and write it to the
+// output parameter given in the constructor.
+class PPResultAndExceptionToNPResult {
+ public:
+ // The object_var parameter is the object to associate any exception with.
+ // It may not be NULL. This class does not take a ref, so it must remain
+ // valid for the lifetime of this object.
+ //
+ // The np_result parameter is the NPAPI result output parameter. This may be
+ // NULL if there is no NPVariant result (like for HasProperty). If this is
+ // specified, you must call SetResult() to set it. If it is not, you must
+ // call CheckExceptionForNoResult to do the exception checking with no result
+ // conversion.
+ PPResultAndExceptionToNPResult(PluginObject* object_var,
+ NPVariant* np_result)
+ : object_var_(object_var),
+ np_result_(np_result),
+ exception_(PP_MakeVoid()),
+ success_(false),
+ checked_exception_(false) {
+ }
+
+ ~PPResultAndExceptionToNPResult() {
+ // The user should have called SetResult or CheckExceptionForNoResult
+ // before letting this class go out of scope, or the exception will have
+ // been lost.
+ DCHECK(checked_exception_);
+
+ ObjectVar::PluginReleasePPVar(exception_);
+ }
+
+ // Returns true if an exception has been set.
+ bool has_exception() const { return exception_.type != PP_VARTYPE_VOID; }
+
+ // Returns a pointer to the exception. You would pass this to the PPAPI
+ // function as the exception parameter. If it is set to non-void, this object
+ // will take ownership of destroying it.
+ PP_Var* exception() { return &exception_; }
+
+ // Returns true if everything succeeded with no exception. This is valid only
+ // after calling SetResult/CheckExceptionForNoResult.
+ bool success() const {
+ DCHECK(checked_exception_);
+ return success_;
+ }
+
+ // Call this with the return value of the PPAPI function. It will convert
+ // the result to the NPVariant output parameter and pass any exception on to
+ // the JS engine. It will update the success flag and return it.
+ bool SetResult(PP_Var result) {
+ DCHECK(!checked_exception_); // Don't call more than once.
+ DCHECK(np_result_); // Should be expecting a result.
+
+ checked_exception_ = true;
+
+ if (has_exception()) {
+ ThrowException();
+ success_ = false;
+ } else if (!PPVarToNPVariant(result, np_result_)) {
+ WebBindings::setException(object_var_->GetNPObject(),
+ kInvalidPluginValue);
+ success_ = false;
+ } else {
+ success_ = true;
+ }
+
+ // No matter what happened, we need to release the reference to the
+ // value passed in. On success, a reference to this value will be in
+ // the np_result_.
+ Var::PluginReleasePPVar(result);
+ return success_;
+ }
+
+ // Call this after calling a PPAPI function that could have set the
+ // exception. It will pass the exception on to the JS engine and update
+ // the success flag.
+ //
+ // The success flag will be returned.
+ bool CheckExceptionForNoResult() {
+ DCHECK(!checked_exception_); // Don't call more than once.
+ DCHECK(!np_result_); // Can't have a result when doing this.
+
+ checked_exception_ = true;
+
+ if (has_exception()) {
+ ThrowException();
+ success_ = false;
+ return false;
+ }
+ success_ = true;
+ return true;
+ }
+
+ // Call this to ignore any exception. This prevents the DCHECK from failing
+ // in the destructor.
+ void IgnoreException() {
+ checked_exception_ = true;
+ }
+
+ private:
+ // Throws the current exception to JS. The exception must be set.
+ void ThrowException() {
+ scoped_refptr<StringVar> string(StringVar::FromPPVar(exception_));
+ if (string) {
+ WebBindings::setException(object_var_->GetNPObject(),
+ string->value().c_str());
+ }
+ }
+
+ PluginObject* object_var_; // Non-owning ref (see constructor).
+ NPVariant* np_result_; // Output value, possibly NULL (see constructor).
+ PP_Var exception_; // Exception set by the PPAPI call. We own a ref to it.
+ bool success_; // See the success() function above.
+ bool checked_exception_; // SetResult/CheckExceptionForNoResult was called.
+
+ DISALLOW_COPY_AND_ASSIGN(PPResultAndExceptionToNPResult);
+};
+
+// NPObjectAccessorWithIdentifier ----------------------------------------------
+
+// Helper class for our NPObject wrapper. This converts a call from WebKit
+// where it gives us an NPObject and an NPIdentifier to an easily-accessible
+// ObjectVar (corresponding to the NPObject) and PP_Var (corresponding to the
+// NPIdentifier).
+//
+// If the NPObject or identifier is invalid, we'll set is_valid() to false.
+// The caller should check is_valid() before doing anything with the class.
+//
+// JS can't have integer functions, so when dealing with these, we don't want
+// to allow integer identifiers. The calling code can decode if it wants to
+// allow integer identifiers (like for property access) or prohibit them
+// (like for method calling) by setting |allow_integer_identifier|. If this
+// is false and the identifier is an integer, we'll set is_valid() to false.
+//
+// Getting an integer identifier in this case should be impossible. V8
+// shouldn't be allowing this, and the Pepper Var calls from the plugin are
+// supposed to error out before calling into V8 (which will then call us back).
+// Aside from an egregious error, the only time this could happen is an NPAPI
+// plugin calling us.
+class NPObjectAccessorWithIdentifier {
+ public:
+ NPObjectAccessorWithIdentifier(NPObject* object,
+ NPIdentifier identifier,
+ bool allow_integer_identifier)
+ : object_(PluginObject::FromNPObject(object)),
+ identifier_(PP_MakeVoid()) {
+ if (object_) {
+ identifier_ = Var::NPIdentifierToPPVar(object_->module(), identifier);
+ if (identifier_.type == PP_VARTYPE_INT32 && !allow_integer_identifier)
+ identifier_.type = PP_VARTYPE_VOID; // Make the identifier invalid.
+ }
+ }
+
+ ~NPObjectAccessorWithIdentifier() {
+ Var::PluginReleasePPVar(identifier_);
+ }
+
+ // Returns true if both the object and identifier are valid.
+ bool is_valid() const {
+ return object_ && identifier_.type != PP_VARTYPE_VOID;
+ }
+
+ PluginObject* object() { return object_; }
+ PP_Var identifier() const { return identifier_; }
+
+ private:
+ PluginObject* object_;
+ PP_Var identifier_;
+
+ DISALLOW_COPY_AND_ASSIGN(NPObjectAccessorWithIdentifier);
+};
+
+// NPObject implementation in terms of PPP_Class -------------------------------
+
+NPObject* WrapperClass_Allocate(NPP npp, NPClass* unused) {
+ return PluginObject::AllocateObjectWrapper();
+}
+
+void WrapperClass_Deallocate(NPObject* np_object) {
+ PluginObject* plugin_object = PluginObject::FromNPObject(np_object);
+ if (!plugin_object)
+ return;
+ plugin_object->ppp_class()->Deallocate(plugin_object->ppp_class_data());
+ delete plugin_object;
+}
+
+void WrapperClass_Invalidate(NPObject* object) {
+}
+
+bool WrapperClass_HasMethod(NPObject* object, NPIdentifier method_name) {
+ NPObjectAccessorWithIdentifier accessor(object, method_name, false);
+ if (!accessor.is_valid())
+ return false;
+
+ PPResultAndExceptionToNPResult result_converter(accessor.object(), NULL);
+ bool rv = accessor.object()->ppp_class()->HasMethod(
+ accessor.object()->ppp_class_data(), accessor.identifier(),
+ result_converter.exception());
+ result_converter.CheckExceptionForNoResult();
+ return rv;
+}
+
+bool WrapperClass_Invoke(NPObject* object, NPIdentifier method_name,
+ const NPVariant* argv, uint32_t argc,
+ NPVariant* result) {
+ NPObjectAccessorWithIdentifier accessor(object, method_name, false);
+ if (!accessor.is_valid())
+ return false;
+
+ PPResultAndExceptionToNPResult result_converter(accessor.object(), result);
+ PPVarArrayFromNPVariantArray args(accessor.object()->module(), argc, argv);
+
+ return result_converter.SetResult(accessor.object()->ppp_class()->Call(
+ accessor.object()->ppp_class_data(), accessor.identifier(),
+ argc, args.array(), result_converter.exception()));
+}
+
+bool WrapperClass_InvokeDefault(NPObject* np_object, const NPVariant* argv,
+ uint32_t argc, NPVariant* result) {
+ PluginObject* obj = PluginObject::FromNPObject(np_object);
+ if (!obj)
+ return false;
+
+ PPVarArrayFromNPVariantArray args(obj->module(), argc, argv);
+ PPResultAndExceptionToNPResult result_converter(obj, result);
+
+ result_converter.SetResult(obj->ppp_class()->Call(
+ obj->ppp_class_data(), PP_MakeVoid(), argc, args.array(),
+ result_converter.exception()));
+ return result_converter.success();
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+bool WrapperClass_HasProperty(NPObject* object, NPIdentifier property_name) {
+ NPObjectAccessorWithIdentifier accessor(object, property_name, true);
+ if (!accessor.is_valid())
+ return false;
+
+ PPResultAndExceptionToNPResult result_converter(accessor.object(), NULL);
+ bool rv = accessor.object()->ppp_class()->HasProperty(
+ accessor.object()->ppp_class_data(), accessor.identifier(),
+ result_converter.exception());
+ result_converter.CheckExceptionForNoResult();
+ return rv;
+}
+
+bool WrapperClass_GetProperty(NPObject* object, NPIdentifier property_name,
+ NPVariant* result) {
+ NPObjectAccessorWithIdentifier accessor(object, property_name, true);
+ if (!accessor.is_valid())
+ return false;
+
+ PPResultAndExceptionToNPResult result_converter(accessor.object(), result);
+ return result_converter.SetResult(accessor.object()->ppp_class()->GetProperty(
+ accessor.object()->ppp_class_data(), accessor.identifier(),
+ result_converter.exception()));
+}
+
+bool WrapperClass_SetProperty(NPObject* object, NPIdentifier property_name,
+ const NPVariant* value) {
+ NPObjectAccessorWithIdentifier accessor(object, property_name, true);
+ if (!accessor.is_valid())
+ return false;
+
+ PPResultAndExceptionToNPResult result_converter(accessor.object(), NULL);
+ PP_Var value_var = Var::NPVariantToPPVar(accessor.object()->module(), value);
+ accessor.object()->ppp_class()->SetProperty(
+ accessor.object()->ppp_class_data(), accessor.identifier(), value_var,
+ result_converter.exception());
+ Var::PluginReleasePPVar(value_var);
+ return result_converter.CheckExceptionForNoResult();
+}
+
+bool WrapperClass_RemoveProperty(NPObject* object, NPIdentifier property_name) {
+ NPObjectAccessorWithIdentifier accessor(object, property_name, true);
+ if (!accessor.is_valid())
+ return false;
+
+ PPResultAndExceptionToNPResult result_converter(accessor.object(), NULL);
+ accessor.object()->ppp_class()->RemoveProperty(
+ accessor.object()->ppp_class_data(), accessor.identifier(),
+ result_converter.exception());
+ return result_converter.CheckExceptionForNoResult();
+}
+
+bool WrapperClass_Enumerate(NPObject* object, NPIdentifier** values,
+ uint32_t* count) {
+ *values = NULL;
+ *count = 0;
+ PluginObject* obj = PluginObject::FromNPObject(object);
+ if (!obj)
+ return false;
+
+ uint32_t property_count = 0;
+ PP_Var* properties = NULL; // Must be freed!
+ PPResultAndExceptionToNPResult result_converter(obj, NULL);
+ obj->ppp_class()->GetAllPropertyNames(obj->ppp_class_data(),
+ &property_count, &properties,
+ result_converter.exception());
+
+ // Convert the array of PP_Var to an array of NPIdentifiers. If any
+ // conversions fail, we will set the exception.
+ if (!result_converter.has_exception()) {
+ if (property_count > 0) {
+ *values = static_cast<NPIdentifier*>(
+ malloc(sizeof(NPIdentifier) * property_count));
+ *count = 0; // Will be the number of items successfully converted.
+ for (uint32_t i = 0; i < property_count; ++i) {
+ if (!((*values)[i] = Var::PPVarToNPIdentifier(properties[i]))) {
+ // Throw an exception for the failed convertion.
+ *result_converter.exception() = StringVar::StringToPPVar(
+ obj->module(), kInvalidValueException);
+ break;
+ }
+ (*count)++;
+ }
+
+ if (result_converter.has_exception()) {
+ // We don't actually have to free the identifiers we converted since
+ // all identifiers leak anyway :( .
+ free(*values);
+ *values = NULL;
+ *count = 0;
+ }
+ }
+ }
+
+ // This will actually throw the exception, either from GetAllPropertyNames,
+ // or if anything was set during the conversion process.
+ result_converter.CheckExceptionForNoResult();
+
+ // Release the PP_Var that the plugin allocated. On success, they will all
+ // be converted to NPVariants, and on failure, we want them to just go away.
+ for (uint32_t i = 0; i < property_count; ++i)
+ Var::PluginReleasePPVar(properties[i]);
+ free(properties);
+ return result_converter.success();
+}
+
+bool WrapperClass_Construct(NPObject* object, const NPVariant* argv,
+ uint32_t argc, NPVariant* result) {
+ PluginObject* obj = PluginObject::FromNPObject(object);
+ if (!obj)
+ return false;
+
+ PPVarArrayFromNPVariantArray args(obj->module(), argc, argv);
+ PPResultAndExceptionToNPResult result_converter(obj, result);
+ return result_converter.SetResult(obj->ppp_class()->Construct(
+ obj->ppp_class_data(), argc, args.array(),
+ result_converter.exception()));
+}
+
+const NPClass wrapper_class = {
+ NP_CLASS_STRUCT_VERSION,
+ WrapperClass_Allocate,
+ WrapperClass_Deallocate,
+ WrapperClass_Invalidate,
+ WrapperClass_HasMethod,
+ WrapperClass_Invoke,
+ WrapperClass_InvokeDefault,
+ WrapperClass_HasProperty,
+ WrapperClass_GetProperty,
+ WrapperClass_SetProperty,
+ WrapperClass_RemoveProperty,
+ WrapperClass_Enumerate,
+ WrapperClass_Construct
+};
+
+} // namespace
+
+// PluginObject -------------------------------------------------------------
+
+struct PluginObject::NPObjectWrapper : public NPObject {
+ // Points to the var object that owns this wrapper. This value may be NULL
+ // if there is no var owning this wrapper. This can happen if the plugin
+ // releases all references to the var, but a reference to the underlying
+ // NPObject is still held by script on the page.
+ PluginObject* obj;
+};
+
+PluginObject::PluginObject(PluginModule* module,
+ NPObjectWrapper* object_wrapper,
+ const PPP_Class* ppp_class,
+ void* ppp_class_data)
+ : module_(module),
+ object_wrapper_(object_wrapper),
+ ppp_class_(ppp_class),
+ ppp_class_data_(ppp_class_data) {
+ // Make the object wrapper refer back to this class so our NPObject
+ // implementation can call back into the Pepper layer.
+ object_wrapper_->obj = this;
+ module_->AddPluginObject(this);
+}
+
+PluginObject::~PluginObject() {
+ // The wrapper we made for this NPObject may still have a reference to it
+ // from JavaScript, so we clear out its ObjectVar back pointer which will
+ // cause all calls "up" to the plugin to become NOPs. Our ObjectVar base
+ // class will release our reference to the object, which may or may not
+ // delete the NPObject.
+ DCHECK(object_wrapper_->obj == this);
+ object_wrapper_->obj = NULL;
+ module_->RemovePluginObject(this);
+}
+
+PP_Var PluginObject::Create(PluginModule* module,
+ const PPP_Class* ppp_class,
+ void* ppp_class_data) {
+ // This will internally end up calling our AllocateObjectWrapper via the
+ // WrapperClass_Allocated function which will have created an object wrapper
+ // appropriate for this class (derived from NPObject).
+ NPObjectWrapper* wrapper = static_cast<NPObjectWrapper*>(
+ WebBindings::createObject(NULL, const_cast<NPClass*>(&wrapper_class)));
+
+ // This object will register itself both with the NPObject and with the
+ // PluginModule. The NPObject will normally handle its lifetime, and it
+ // will get deleted in the destroy method. It may also get deleted when the
+ // plugin module is deallocated.
+ new PluginObject(module, wrapper, ppp_class, ppp_class_data);
+
+ // We can just use a normal ObjectVar to refer to this object from the
+ // plugin. It will hold a ref to the underlying NPObject which will in turn
+ // hold our pluginObject.
+ return ObjectVar::NPObjectToPPVar(module, wrapper);
+}
+
+NPObject* PluginObject::GetNPObject() const {
+ return object_wrapper_;
+}
+
+// static
+bool PluginObject::IsInstanceOf(NPObject* np_object,
+ const PPP_Class* ppp_class,
+ void** ppp_class_data) {
+ // Validate that this object is implemented by our wrapper class before
+ // trying to get the PluginObject.
+ if (np_object->_class != &wrapper_class)
+ return false;
+
+ PluginObject* plugin_object = FromNPObject(np_object);
+ if (!plugin_object)
+ return false; // Object is no longer alive.
+
+ if (plugin_object->ppp_class() != ppp_class)
+ return false;
+ if (ppp_class_data)
+ *ppp_class_data = plugin_object->ppp_class_data();
+ return true;
+}
+
+// static
+PluginObject* PluginObject::FromNPObject(NPObject* object) {
+ return static_cast<NPObjectWrapper*>(object)->obj;
+}
+
+// static
+NPObject* PluginObject::AllocateObjectWrapper() {
+ NPObjectWrapper* wrapper = new NPObjectWrapper;
+ memset(wrapper, 0, sizeof(NPObjectWrapper));
+ return wrapper;
+}
+
+} // namespace pepper
diff --git a/webkit/glue/plugins/pepper_plugin_object.h b/webkit/glue/plugins/pepper_plugin_object.h
new file mode 100644
index 0000000..7715a81
--- /dev/null
+++ b/webkit/glue/plugins/pepper_plugin_object.h
@@ -0,0 +1,89 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_GLUE_PLUGINS_PEPPER_PLUGIN_OBJECT_H_
+#define WEBKIT_GLUE_PLUGINS_PEPPER_PLUGIN_OBJECT_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+
+struct PP_Var;
+struct PPP_Class;
+typedef struct NPObject NPObject;
+typedef struct _NPVariant NPVariant;
+
+namespace pepper {
+
+class PluginModule;
+
+class PluginObject {
+ public:
+ virtual ~PluginObject();
+
+ // Allocates a new PluginObject and returns it as a PP_Var with a
+ // refcount of 1.
+ static PP_Var Create(PluginModule* module,
+ const PPP_Class* ppp_class,
+ void* ppp_class_data);
+
+ PluginModule* module() const { return module_; }
+
+ const PPP_Class* ppp_class() { return ppp_class_; }
+ void* ppp_class_data() { return ppp_class_data_; };
+
+ NPObject* GetNPObject() const;
+
+ // Returns true if the given var is an object implemented by the same plugin
+ // that owns the var object, and that the class matches. If it matches,
+ // returns true and places the class data into |*ppp_class_data| (which can
+ // optionally be NULL if no class data is desired).
+ static bool IsInstanceOf(NPObject* np_object,
+ const PPP_Class* ppp_class,
+ void** ppp_class_data);
+
+ // Converts the given NPObject to the corresponding ObjectVar.
+ //
+ // The given NPObject must be one corresponding to a PluginObject or this
+ // will crash. If the object is a PluginObject but the plugin has gone
+ // away (the object could still be alive because of a reference from JS),
+ // then the return value will be NULL.
+ static PluginObject* FromNPObject(NPObject* object);
+
+ // Allocates a plugin wrapper object and returns it as an NPObject. This is
+ // used internally only.
+ static NPObject* AllocateObjectWrapper();
+
+ private:
+ struct NPObjectWrapper;
+
+ // This object must be created using the CreateObject function of the which
+ // will set up the correct NPObject.
+ //
+ // The NPObjectWrapper (an NPObject) should already have the reference
+ // incremented on it, and this class will take ownership of that reference.
+ PluginObject(PluginModule* module,
+ NPObjectWrapper* object_wrapper,
+ const PPP_Class* ppp_class,
+ void* ppp_class_data);
+
+ PluginModule* module_;
+
+ // Holds a pointer to the NPObject wrapper backing the var. This class
+ // derives from NPObject and we hold a reference to it, so it must be
+ // refcounted. When the type is not an object, this value will be NULL.
+ //
+ // We don't actually own this pointer, it's the NPObject that actually
+ // owns us.
+ NPObjectWrapper* object_wrapper_;
+
+ const PPP_Class* ppp_class_;
+ void* ppp_class_data_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginObject);
+};
+
+} // namespace pepper
+
+#endif // WEBKIT_GLUE_PLUGINS_PEPPER_PLUGIN_OBJECT_H_
diff --git a/webkit/glue/plugins/pepper_private2.cc b/webkit/glue/plugins/pepper_private2.cc
new file mode 100644
index 0000000..9a740aa
--- /dev/null
+++ b/webkit/glue/plugins/pepper_private2.cc
@@ -0,0 +1,32 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/glue/plugins/pepper_private2.h"
+
+#include "webkit/glue/plugins/pepper_plugin_instance.h"
+#include "webkit/glue/plugins/ppb_private2.h"
+
+namespace pepper {
+
+namespace {
+
+void SetInstanceAlwaysOnTop(PP_Instance pp_instance, bool on_top) {
+ PluginInstance* instance = PluginInstance::FromPPInstance(pp_instance);
+ if (!instance)
+ return;
+ instance->set_always_on_top(on_top);
+}
+
+const PPB_Private2 ppb_private2 = {
+ &SetInstanceAlwaysOnTop
+};
+
+} // namespace
+
+// static
+const PPB_Private2* Private2::GetInterface() {
+ return &ppb_private2;
+}
+
+} // namespace pepper
diff --git a/webkit/glue/plugins/pepper_private2.h b/webkit/glue/plugins/pepper_private2.h
new file mode 100644
index 0000000..492669a
--- /dev/null
+++ b/webkit/glue/plugins/pepper_private2.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_GLUE_PLUGINS_PEPPER_PRIVATE2_H_
+#define WEBKIT_GLUE_PLUGINS_PEPPER_PRIVATE2_H_
+
+#include "webkit/glue/plugins/pepper_resource.h"
+
+struct PPB_Private2;
+
+namespace pepper {
+
+class Private2 {
+ public:
+ // Returns a pointer to the interface implementing PPB_Private2 that is
+ // exposed to the plugin.
+ static const PPB_Private2* GetInterface();
+};
+
+} // namespace pepper
+
+#endif // WEBKIT_GLUE_PLUGINS_PEPPER_PRIVATE2_H_
diff --git a/webkit/glue/plugins/pepper_transport.cc b/webkit/glue/plugins/pepper_transport.cc
new file mode 100644
index 0000000..ed5e05f
--- /dev/null
+++ b/webkit/glue/plugins/pepper_transport.cc
@@ -0,0 +1,139 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/glue/plugins/pepper_transport.h"
+
+#include "base/singleton.h"
+#include "base/thread_local.h"
+#include "third_party/ppapi/c/dev/ppb_transport_dev.h"
+#include "webkit/glue/plugins/pepper_plugin_instance.h"
+#include "webkit/glue/plugins/pepper_plugin_module.h"
+
+namespace pepper {
+
+namespace {
+
+// Creates a new transport object with the specified name
+// using the specified protocol.
+PP_Resource CreateTransport(PP_Module module,
+ const char* name,
+ const char* proto) {
+ // TODO(juberti): implement me
+ PP_Resource p(0);
+ return p;
+}
+
+// Returns whether or not resource is Transport
+bool IsTransport(PP_Resource resource) {
+ return !!Resource::GetAs<Transport>(resource);
+}
+
+// Returns whether the transport is currently writable
+// (i.e. can send data to the remote peer)
+bool IsWritable(PP_Resource transport) {
+ // TODO(juberti): impelement me
+ return false;
+}
+
+
+// TODO(juberti): other getters/setters
+// connect state
+// connect type, protocol
+// RTT
+
+
+// Establishes a connection to the remote peer.
+// Returns PP_ERROR_WOULDBLOCK and notifies on |cb|
+// when connectivity is established (or timeout occurs).
+int32_t Connect(PP_Resource transport,
+ PP_CompletionCallback cb) {
+ // TODO(juberti): impelement me
+ return 0;
+}
+
+
+// Obtains another ICE candidate address to be provided
+// to the remote peer. Returns PP_ERROR_WOULDBLOCK
+// if there are no more addresses to be sent.
+int32_t GetNextAddress(PP_Resource transport,
+ PP_Var* address,
+ PP_CompletionCallback cb) {
+ // TODO(juberti): implement me
+ return 0;
+}
+
+
+// Provides an ICE candidate address that was received
+// from the remote peer.
+int32_t ReceiveRemoteAddress(PP_Resource transport,
+ PP_Var address) {
+ // TODO(juberti): implement me
+ return 0;
+}
+
+
+// Like recv(), receives data. Returns PP_ERROR_WOULDBLOCK
+// if there is currently no data to receive.
+int32_t Recv(PP_Resource transport,
+ void* data,
+ uint32_t len,
+ PP_CompletionCallback cb) {
+ // TODO(juberti): implement me
+ return 0;
+}
+
+
+// Like send(), sends data. Returns PP_ERROR_WOULDBLOCK
+// if the socket is currently flow-controlled.
+int32_t Send(PP_Resource transport,
+ const void* data,
+ uint32_t len,
+ PP_CompletionCallback cb) {
+ // TODO(juberti): implement me
+ return 0;
+}
+
+
+// Disconnects from the remote peer.
+int32_t Close(PP_Resource transport) {
+ // TODO(juberti): implement me
+ return 0;
+}
+
+
+const PPB_Transport_Dev ppb_transport = {
+ &CreateTransport,
+ &IsTransport,
+ &IsWritable,
+ &Connect,
+ &GetNextAddress,
+ &ReceiveRemoteAddress,
+ &Recv,
+ &Send,
+ &Close,
+};
+
+} // namespace
+
+Transport::Transport(PluginModule* module)
+ : Resource(module) {
+ // TODO(juberti): impl
+}
+
+const PPB_Transport_Dev* Transport::GetInterface() {
+ return &ppb_transport;
+}
+
+Transport::~Transport() {
+ // TODO(juberti): teardown
+}
+
+bool Transport::Init(const char* name,
+ const char* proto) {
+ // TODO(juberti): impl
+ return false;
+}
+
+} // namespace pepper
+
diff --git a/webkit/glue/plugins/pepper_transport.h b/webkit/glue/plugins/pepper_transport.h
new file mode 100644
index 0000000..1e6e56f
--- /dev/null
+++ b/webkit/glue/plugins/pepper_transport.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_GLUE_PLUGINS_PEPPER_TRANSPORT_H_
+#define WEBKIT_GLUE_PLUGINS_PEPPER_TRANSPORT_H_
+
+#include "base/scoped_ptr.h"
+#include "third_party/ppapi/c/pp_instance.h"
+#include "webkit/glue/plugins/pepper_plugin_delegate.h"
+#include "webkit/glue/plugins/pepper_resource.h"
+
+struct PPB_Transport_Dev;
+
+namespace pepper {
+
+class Transport : public Resource {
+ public:
+ explicit Transport(PluginModule* module);
+ virtual ~Transport();
+ static const PPB_Transport_Dev* GetInterface();
+ virtual Transport* AsTransport() {
+ return this;
+ }
+ bool Init(const char* name,
+ const char* proto);
+ private:
+
+ DISALLOW_COPY_AND_ASSIGN(Transport);
+};
+
+} // namespace pepper
+
+#endif // WEBKIT_GLUE_PLUGINS_PEPPER_TRANSPORT_H_
+
diff --git a/webkit/glue/plugins/pepper_url_util.cc b/webkit/glue/plugins/pepper_url_util.cc
new file mode 100644
index 0000000..3f9a54f
--- /dev/null
+++ b/webkit/glue/plugins/pepper_url_util.cc
@@ -0,0 +1,176 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/glue/plugins/pepper_url_util.h"
+
+#include "googleurl/src/gurl.h"
+#include "third_party/ppapi/c/dev/ppb_url_util_dev.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebElement.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebNode.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebPluginContainer.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
+#include "webkit/glue/plugins/pepper_plugin_instance.h"
+#include "webkit/glue/plugins/pepper_string.h"
+#include "webkit/glue/plugins/pepper_var.h"
+
+namespace pepper {
+
+namespace {
+
+void ConvertComponent(const url_parse::Component& input,
+ PP_UrlComponent_Dev* output) {
+ output->begin = input.begin;
+ output->len = input.len;
+}
+
+// Output can be NULL to specify "do nothing." This rule is followed by all the
+// url util functions, so we implement it once here.
+void ConvertComponents(const url_parse::Parsed& input,
+ PP_UrlComponents_Dev* output) {
+ if (!output)
+ return;
+
+ ConvertComponent(input.scheme, &output->scheme);
+ ConvertComponent(input.username, &output->username);
+ ConvertComponent(input.password, &output->password);
+ ConvertComponent(input.host, &output->host);
+ ConvertComponent(input.port, &output->port);
+ ConvertComponent(input.path, &output->path);
+ ConvertComponent(input.query, &output->query);
+ ConvertComponent(input.ref, &output->ref);
+}
+
+// Used for returning the given GURL from a PPAPI function, with an optional
+// out param indicating the components.
+PP_Var GenerateUrlReturn(PluginModule* module, const GURL& url,
+ PP_UrlComponents_Dev* components) {
+ if (!url.is_valid())
+ return PP_MakeNull();
+ ConvertComponents(url.parsed_for_possibly_invalid_spec(), components);
+ return StringVar::StringToPPVar(module, url.possibly_invalid_spec());
+}
+
+// Sets |*security_origin| to be the WebKit security origin associated with the
+// document containing the given plugin instance. On success, returns true. If
+// the instance is invalid, returns false and |*security_origin| will be
+// unchanged.
+bool SecurityOriginForInstance(PP_Instance instance_id,
+ WebKit::WebSecurityOrigin* security_origin) {
+ PluginInstance* instance = PluginInstance::FromPPInstance(instance_id);
+ if (!instance)
+ return false;
+
+ WebKit::WebElement plugin_element = instance->container()->element();
+ WebKit::WebFrame* plugin_frame = plugin_element.document().frame();
+ if (!plugin_frame)
+ return false;
+
+ *security_origin = plugin_frame->securityOrigin();
+ return true;
+}
+
+PP_Var Canonicalize(PP_Var url, PP_UrlComponents_Dev* components) {
+ scoped_refptr<StringVar> url_string(StringVar::FromPPVar(url));
+ if (!url_string)
+ return PP_MakeNull();
+ return GenerateUrlReturn(url_string->module(),
+ GURL(url_string->value()), components);
+}
+
+PP_Var ResolveRelativeToUrl(PP_Var base_url,
+ PP_Var relative,
+ PP_UrlComponents_Dev* components) {
+ scoped_refptr<StringVar> base_url_string(StringVar::FromPPVar(base_url));
+ scoped_refptr<StringVar> relative_string(StringVar::FromPPVar(relative));
+ if (!base_url_string || !relative_string)
+ return PP_MakeNull();
+
+ GURL base_gurl(base_url_string->value());
+ if (!base_gurl.is_valid())
+ return PP_MakeNull();
+ return GenerateUrlReturn(base_url_string->module(),
+ base_gurl.Resolve(relative_string->value()),
+ components);
+}
+
+PP_Var ResolveRelativeToDocument(PP_Instance instance_id,
+ PP_Var relative,
+ PP_UrlComponents_Dev* components) {
+ PluginInstance* instance = PluginInstance::FromPPInstance(instance_id);
+ if (!instance)
+ return PP_MakeNull();
+
+ scoped_refptr<StringVar> relative_string(StringVar::FromPPVar(relative));
+ if (!relative_string)
+ return PP_MakeNull();
+
+ WebKit::WebElement plugin_element = instance->container()->element();
+ GURL document_url = plugin_element.document().baseURL();
+ return GenerateUrlReturn(instance->module(),
+ document_url.Resolve(relative_string->value()),
+ components);
+}
+
+bool IsSameSecurityOrigin(PP_Var url_a, PP_Var url_b) {
+ scoped_refptr<StringVar> url_a_string(StringVar::FromPPVar(url_a));
+ scoped_refptr<StringVar> url_b_string(StringVar::FromPPVar(url_b));
+ if (!url_a_string || !url_b_string)
+ return false;
+
+ GURL gurl_a(url_a_string->value());
+ GURL gurl_b(url_b_string->value());
+ if (!gurl_a.is_valid() || !gurl_b.is_valid())
+ return false;
+
+ return gurl_a.GetOrigin() == gurl_b.GetOrigin();
+}
+
+bool DocumentCanRequest(PP_Instance instance, PP_Var url) {
+ scoped_refptr<StringVar> url_string(StringVar::FromPPVar(url));
+ if (!url_string)
+ return false;
+
+ WebKit::WebSecurityOrigin security_origin;
+ if (!SecurityOriginForInstance(instance, &security_origin))
+ return false;
+
+ GURL gurl(url_string->value());
+ if (!gurl.is_valid())
+ return false;
+
+ return security_origin.canRequest(gurl);
+}
+
+bool DocumentCanAccessDocument(PP_Instance active, PP_Instance target) {
+ WebKit::WebSecurityOrigin active_origin;
+ if (!SecurityOriginForInstance(active, &active_origin))
+ return false;
+
+ WebKit::WebSecurityOrigin target_origin;
+ if (!SecurityOriginForInstance(active, &target_origin))
+ return false;
+
+ return active_origin.canAccess(target_origin);
+}
+
+} // namespace
+
+const PPB_UrlUtil_Dev ppb_url_util = {
+ &Canonicalize,
+ &ResolveRelativeToUrl,
+ &ResolveRelativeToDocument,
+ &IsSameSecurityOrigin,
+ &DocumentCanRequest,
+ &DocumentCanAccessDocument
+};
+
+// static
+const PPB_UrlUtil_Dev* UrlUtil::GetInterface() {
+ return &ppb_url_util;
+}
+
+} // namespace pepper
diff --git a/webkit/glue/plugins/pepper_url_util.h b/webkit/glue/plugins/pepper_url_util.h
new file mode 100644
index 0000000..ffb7c76
--- /dev/null
+++ b/webkit/glue/plugins/pepper_url_util.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_GLUE_PLUGINS_PEPPER_URL_UTIL_H_
+#define WEBKIT_GLUE_PLUGINS_PEPPER_URL_UTIL_H_
+
+struct PPB_UrlUtil_Dev;
+
+namespace pepper {
+
+class UrlUtil {
+ public:
+ static const PPB_UrlUtil_Dev* GetInterface();
+};
+
+} // namespace pepper
+
+#endif // WEBKIT_GLUE_PLUGINS_PEPPER_URL_UTIL_H_
diff --git a/webkit/glue/plugins/pepper_video_decoder.cc b/webkit/glue/plugins/pepper_video_decoder.cc
new file mode 100644
index 0000000..ed572b3
--- /dev/null
+++ b/webkit/glue/plugins/pepper_video_decoder.cc
@@ -0,0 +1,140 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "webkit/glue/plugins/pepper_video_decoder.h"
+
+#include "base/logging.h"
+#include "third_party/ppapi/c/dev/pp_video_dev.h"
+#include "third_party/ppapi/c/dev/ppb_video_decoder_dev.h"
+#include "third_party/ppapi/c/pp_completion_callback.h"
+#include "third_party/ppapi/c/pp_errors.h"
+#include "webkit/glue/plugins/pepper_file_ref.h"
+#include "webkit/glue/plugins/pepper_plugin_instance.h"
+#include "webkit/glue/plugins/pepper_resource_tracker.h"
+
+namespace pepper {
+
+namespace {
+
+bool GetConfig(PP_Instance instance_id,
+ PP_VideoCodecId_Dev codec,
+ PP_VideoConfig_Dev* configs,
+ int32_t config_size,
+ int32_t *num_config) {
+ PluginInstance* instance = PluginInstance::FromPPInstance(instance_id);
+ *num_config = 0;
+ if (!instance)
+ return false;
+
+ // Get configs based on codec.
+
+ if (configs) {
+ // Fill in the array of configs.
+ }
+
+ // Update *num_config.
+
+ return true;
+}
+
+PP_Resource Create(PP_Instance instance_id,
+ const PP_VideoDecoderConfig_Dev* decoder_config) {
+ PluginInstance* instance = PluginInstance::FromPPInstance(instance_id);
+ if (!instance)
+ return 0;
+
+ scoped_refptr<VideoDecoder> decoder(new VideoDecoder(instance));
+
+ if (!decoder->Init(*decoder_config))
+ return 0;
+
+ return decoder->GetReference();
+}
+
+bool Decode(PP_Resource decoder_id,
+ PP_VideoCompressedDataBuffer_Dev* input_buffer) {
+ scoped_refptr<VideoDecoder> decoder(
+ Resource::GetAs<VideoDecoder>(decoder_id));
+ if (!decoder)
+ return false;
+
+ decoder->Decode(*input_buffer);
+ return true;
+}
+
+int32_t Flush(PP_Resource decoder_id, PP_CompletionCallback callback) {
+ scoped_refptr<VideoDecoder> decoder(
+ Resource::GetAs<VideoDecoder>(decoder_id));
+ if (!decoder)
+ return PP_ERROR_BADRESOURCE;
+
+ return decoder->Flush(callback);
+}
+
+bool ReturnUncompressedDataBuffer(PP_Resource decoder_id,
+ PP_VideoUncompressedDataBuffer_Dev* buffer) {
+ scoped_refptr<VideoDecoder> decoder(
+ Resource::GetAs<VideoDecoder>(decoder_id));
+ if (!decoder)
+ return false;
+
+ return decoder->ReturnUncompressedDataBuffer(*buffer);
+}
+
+const PPB_VideoDecoder_Dev ppb_videodecoder = {
+ &GetConfig,
+ &Create,
+ &Decode,
+ &Flush,
+ &ReturnUncompressedDataBuffer
+};
+
+} // namespace
+
+VideoDecoder::VideoDecoder(PluginInstance* instance)
+ : Resource(instance->module()),
+ instance_(instance) {
+}
+
+VideoDecoder::~VideoDecoder() {
+}
+
+// static
+const PPB_VideoDecoder_Dev* VideoDecoder::GetInterface() {
+ return &ppb_videodecoder;
+}
+
+bool VideoDecoder::Init(const PP_VideoDecoderConfig_Dev& decoder_config) {
+ if (!instance())
+ return false;
+
+ platform_video_decoder_.reset(
+ instance()->delegate()->CreateVideoDecoder(decoder_config));
+
+ return platform_video_decoder_.get()? true : false;
+}
+
+bool VideoDecoder::Decode(PP_VideoCompressedDataBuffer_Dev& input_buffer) {
+ if (!platform_video_decoder_.get())
+ return false;
+
+ return platform_video_decoder_->Decode(input_buffer);
+}
+
+int32_t VideoDecoder::Flush(PP_CompletionCallback& callback) {
+ if (!platform_video_decoder_.get())
+ return PP_ERROR_FAILED;
+
+ return platform_video_decoder_->Flush(callback);
+}
+
+bool VideoDecoder::ReturnUncompressedDataBuffer(
+ PP_VideoUncompressedDataBuffer_Dev& buffer) {
+ if (!platform_video_decoder_.get())
+ return false;
+
+ return platform_video_decoder_->ReturnUncompressedDataBuffer(buffer);
+}
+
+} // namespace pepper
diff --git a/webkit/glue/plugins/pepper_video_decoder.h b/webkit/glue/plugins/pepper_video_decoder.h
new file mode 100644
index 0000000..c828709
--- /dev/null
+++ b/webkit/glue/plugins/pepper_video_decoder.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_GLUE_PLUGINS_PEPPER_VIDEO_DECODER_H_
+#define WEBKIT_GLUE_PLUGINS_PEPPER_VIDEO_DECODER_H_
+
+#include "base/scoped_ptr.h"
+#include "webkit/glue/plugins/pepper_plugin_delegate.h"
+#include "webkit/glue/plugins/pepper_resource.h"
+
+struct PP_VideoDecoderConfig_Dev;
+struct PP_VideoCompressedDataBuffer_Dev;
+struct PP_VideoUncompressedDataBuffer_Dev;
+struct PPB_VideoDecoder_Dev;
+
+namespace pepper {
+
+class PluginInstance;
+
+class VideoDecoder : public Resource {
+ public:
+ VideoDecoder(PluginInstance* instance);
+ virtual ~VideoDecoder();
+
+ // Returns a pointer to the interface implementing PPB_VideoDecoder that is
+ // exposed to the plugin.
+ static const PPB_VideoDecoder_Dev* GetInterface();
+
+ // Resource overrides.
+ VideoDecoder* AsVideoDecoder() { return this; }
+
+ PluginInstance* instance() { return instance_.get(); }
+
+ // PPB_VideoDecoder implementation.
+ bool Init(const PP_VideoDecoderConfig_Dev& decoder_config);
+ bool Decode(PP_VideoCompressedDataBuffer_Dev& input_buffer);
+ int32_t Flush(PP_CompletionCallback& callback);
+ bool ReturnUncompressedDataBuffer(PP_VideoUncompressedDataBuffer_Dev& buffer);
+
+ private:
+ // This is NULL before initialization, and if this VideoDecoder is
+ // swapped with another.
+ scoped_ptr<PluginDelegate::PlatformVideoDecoder> platform_video_decoder_;
+ scoped_refptr<PluginInstance> instance_;
+};
+
+} // namespace pepper
+
+#endif // WEBKIT_GLUE_PLUGINS_PEPPER_VIDEO_DECODER_H_
diff --git a/webkit/glue/plugins/ppb_private2.h b/webkit/glue/plugins/ppb_private2.h
new file mode 100644
index 0000000..ca45471
--- /dev/null
+++ b/webkit/glue/plugins/ppb_private2.h
@@ -0,0 +1,21 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WEBKIT_GLUE_PLUGINS_PPB_PRIVATE2_H_
+#define WEBKIT_GLUE_PLUGINS_PPB_PRIVATE2_H_
+
+#include "third_party/ppapi/c/pp_instance.h"
+#include "third_party/ppapi/c/pp_module.h"
+#include "third_party/ppapi/c/pp_var.h"
+
+#define PPB_PRIVATE2_INTERFACE "PPB_Private2;1"
+
+struct PPB_Private2 {
+ // Sets or clears the rendering hint that the given plugin instance is always
+ // on top of page content. Somewhat more optimized painting can be used in
+ // this case.
+ void (*SetInstanceAlwaysOnTop)(PP_Instance instance, bool on_top);
+};
+
+#endif // WEBKIT_GLUE_PLUGINS_PPB_PRIVATE2_H_