From 6ac20de010f52e367d184f7565f8193cbc901101 Mon Sep 17 00:00:00 2001 From: "brettw@chromium.org" Date: Wed, 4 Jan 2012 04:47:25 +0000 Subject: Revert 116281 - Move paint aggregator and the completion callback factory. Move paint aggregator and the completion callback factory to the ppapi/helpers directory since they're not strictly wrappers. Review URL: http://codereview.chromium.org/9030001 TBR=brettw@chromium.org Review URL: http://codereview.chromium.org/9086003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@116284 0039d316-1c4b-4281-b951-d872f2087c98 --- ppapi/cpp/completion_callback.h | 551 +++++++++++++++++++- ppapi/cpp/non_thread_safe_ref_count.h | 60 +++ ppapi/cpp/paint_aggregator.cc | 279 ++++++++++ ppapi/cpp/paint_aggregator.h | 174 +++++++ ppapi/cpp/paint_manager.cc | 203 ++++++++ ppapi/cpp/paint_manager.h | 297 +++++++++++ ppapi/example/example.cc | 1 - ppapi/examples/2d/paint_manager_example.cc | 2 +- ppapi/examples/2d/scroll.cc | 4 +- ppapi/examples/audio_input/audio_input.cc | 2 +- ppapi/examples/file_chooser/file_chooser.cc | 1 - ppapi/examples/gles2/gles2.cc | 1 - ppapi/examples/mouse_lock/mouse_lock.cc | 2 +- ppapi/examples/url_loader/streaming.cc | 2 +- ppapi/examples/video_capture/video_capture.cc | 1 - .../src/trusted/plugin/file_downloader.h | 2 +- .../src/trusted/plugin/pnacl_resources.h | 3 +- ppapi/ppapi_sources.gypi | 13 +- ppapi/proxy/ppb_audio_input_proxy.h | 2 +- ppapi/proxy/ppb_audio_proxy.h | 2 +- ppapi/proxy/ppb_broker_proxy.h | 2 +- ppapi/proxy/ppb_file_chooser_proxy.h | 2 +- ppapi/proxy/ppb_file_io_proxy.h | 1 - ppapi/proxy/ppb_file_ref_proxy.h | 2 +- ppapi/proxy/ppb_file_system_proxy.h | 2 +- ppapi/proxy/ppb_flash_menu_proxy.h | 1 - ppapi/proxy/ppb_flash_net_connector_proxy.h | 2 +- ppapi/proxy/ppb_graphics_2d_proxy.h | 2 +- ppapi/proxy/ppb_graphics_3d_proxy.h | 2 +- ppapi/proxy/ppb_instance_proxy.h | 2 +- ppapi/proxy/ppb_url_loader_proxy.h | 2 +- ppapi/proxy/ppb_video_decoder_proxy.h | 2 +- ppapi/tests/DEPS | 1 - ppapi/tests/all_cpp_includes.h | 6 +- ppapi/tests/test_flash.h | 2 +- ppapi/tests/test_paint_aggregator.cc | 2 +- ppapi/tests/test_transport.cc | 2 +- ppapi/tests/testing_instance.h | 2 +- ppapi/utility/DEPS | 14 - ppapi/utility/README.txt | 2 - ppapi/utility/completion_callback_factory.h | 564 --------------------- ppapi/utility/graphics/paint_aggregator.cc | 279 ---------- ppapi/utility/graphics/paint_aggregator.h | 174 ------- ppapi/utility/graphics/paint_manager.cc | 203 -------- ppapi/utility/graphics/paint_manager.h | 297 ----------- ppapi/utility/non_thread_safe_ref_count.h | 60 --- 46 files changed, 1596 insertions(+), 1636 deletions(-) create mode 100644 ppapi/cpp/non_thread_safe_ref_count.h create mode 100644 ppapi/cpp/paint_aggregator.cc create mode 100644 ppapi/cpp/paint_aggregator.h create mode 100644 ppapi/cpp/paint_manager.cc create mode 100644 ppapi/cpp/paint_manager.h delete mode 100644 ppapi/utility/DEPS delete mode 100644 ppapi/utility/README.txt delete mode 100644 ppapi/utility/completion_callback_factory.h delete mode 100644 ppapi/utility/graphics/paint_aggregator.cc delete mode 100644 ppapi/utility/graphics/paint_aggregator.h delete mode 100644 ppapi/utility/graphics/paint_manager.cc delete mode 100644 ppapi/utility/graphics/paint_manager.h delete mode 100644 ppapi/utility/non_thread_safe_ref_count.h (limited to 'ppapi') diff --git a/ppapi/cpp/completion_callback.h b/ppapi/cpp/completion_callback.h index b4564e1..2e5f38b 100644 --- a/ppapi/cpp/completion_callback.h +++ b/ppapi/cpp/completion_callback.h @@ -8,7 +8,7 @@ #include "ppapi/c/pp_completion_callback.h" #include "ppapi/c/pp_errors.h" #include "ppapi/cpp/logging.h" -#include "ppapi/cpp/module.h" +#include "ppapi/cpp/non_thread_safe_ref_count.h" /// @file /// This file defines the API to create and run a callback. @@ -156,6 +156,555 @@ class CompletionCallback { /// @return A CompletionCallback corresponding to a NULL callback. CompletionCallback BlockUntilComplete(); +/// CompletionCallbackFactory may be used to create CompletionCallback +/// objects that are bound to member functions. +/// +/// If a factory is destroyed, then any pending callbacks will be cancelled +/// preventing any bound member functions from being called. The CancelAll() +/// method allows pending callbacks to be cancelled without destroying the +/// factory. +/// +/// Note: CompletionCallbackFactory isn't +/// thread safe, but you can make it more thread-friendly by passing a +/// thread-safe refcounting class as the second template element. However, it +/// only guarantees safety for creating a callback from another thread, the +/// callback itself needs to execute on the same thread as the thread that +/// creates/destroys the factory. With this restriction, it is safe to create +/// the CompletionCallbackFactory on the main thread, create +/// callbacks from any thread and pass them to CallOnMainThread(). +/// +/// Example: +/// +/// @code +/// +/// class MyHandler { +/// public: +/// // If an compiler warns on following using |this| in the initializer +/// // list, use PP_ALLOW_THIS_IN_INITIALIZER_LIST macro. +/// MyHandler() : factory_(this), offset_(0) { +/// } +/// +/// void ProcessFile(const FileRef& file) { +/// CompletionCallback cc = factory_.NewRequiredCallback( +/// &MyHandler::DidOpen); +/// int32_t rv = fio_.Open(file, PP_FileOpenFlag_Read, cc); +/// CHECK(rv == PP_OK_COMPLETIONPENDING); +/// } +/// +/// private: +/// CompletionCallback NewCallback() { +/// return factory_.NewCallback(&MyHandler::DidCompleteIO); +/// } +/// +/// void DidOpen(int32_t result) { +/// if (result == PP_OK) { +/// // The file is open, and we can begin reading. +/// offset_ = 0; +/// ReadMore(); +/// } else { +/// // Failed to open the file with error given by 'result'. +/// } +/// } +/// +/// void DidRead(int32_t result) { +/// if (result > 0) { +/// // buf_ now contains 'result' number of bytes from the file. +/// ProcessBytes(buf_, result); +/// offset_ += result; +/// ReadMore(); +/// } else { +/// // Done reading (possibly with an error given by 'result'). +/// } +/// } +/// +/// void ReadMore() { +/// CompletionCallback cc = +/// factory_.NewOptionalCallback(&MyHandler::DidRead); +/// int32_t rv = fio_.Read(offset_, buf_, sizeof(buf_), +/// cc.pp_completion_callback()); +/// if (rv != PP_OK_COMPLETIONPENDING) +/// cc.Run(rv); +/// } +/// +/// void ProcessBytes(const char* bytes, int32_t length) { +/// // Do work ... +/// } +/// +/// pp::CompletionCallbackFactory factory_; +/// pp::FileIO fio_; +/// char buf_[4096]; +/// int64_t offset_; +/// }; +/// +/// @endcode +/// +template +class CompletionCallbackFactory { + public: + + /// This constructor creates a CompletionCallbackFactory + /// bound to an object. If the constructor is called without an argument, + /// the default value of NULL is used. The user then must call + /// Initialize() to initialize the object. + /// + /// param[in] object Optional parameter. An object whose member functions + /// are to be bound to CompletionCallbacks created by this + /// CompletionCallbackFactory. The default value of this + /// parameter is NULL. + explicit CompletionCallbackFactory(T* object = NULL) + : object_(object) { + InitBackPointer(); + } + + /// Destructor. + ~CompletionCallbackFactory() { + ResetBackPointer(); + } + + /// CancelAll() cancels all CompletionCallbacks allocated from + /// this factory. + void CancelAll() { + ResetBackPointer(); + InitBackPointer(); + } + /// Initialize() binds the CallbackFactory to a particular + /// object. Use this when the object is not available at + /// CallbackFactory creation, and the NULL default + /// is passed to the constructor. The object may only be initialized once, + /// either by the constructor, or by a call to Initialize(). + /// + /// @param[in] object The object whose member functions are to be bound to + /// the CompletionCallback created by this + /// CompletionCallbackFactory. + void Initialize(T* object) { + PP_DCHECK(object); + PP_DCHECK(!object_); // May only initialize once! + object_ = object; + } + + /// GetObject() returns the object that was passed at initialization to + /// Intialize(). + /// + /// @return the object passed to the constructor or Intialize(). + T* GetObject() { + return object_; + } + + /// NewCallback allocates a new, single-use CompletionCallback. + /// The CompletionCallback must be run in order for the memory + /// allocated by the methods to be freed. + /// NewCallback() is equivalent to NewRequiredCallback() below. + /// + /// @param[in] method The method to be invoked upon completion of the + /// operation. + /// + /// @return A CompletionCallback. + template + CompletionCallback NewCallback(Method method) { + PP_DCHECK(object_); + return NewCallbackHelper(Dispatcher0(method)); + } + + /// NewRequiredCallback() allocates a new, single-use + /// CompletionCallback that will always run. The + /// CompletionCallback must be run in order for the memory + /// allocated by the methods to be freed. + /// + /// @param[in] method The method to be invoked upon completion of the + /// operation. + /// + /// @return A CompletionCallback. + template + CompletionCallback NewRequiredCallback(Method method) { + CompletionCallback cc = NewCallback(method); + cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); + return cc; + } + + /// NewOptionalCallback() allocates a new, single-use + /// CompletionCallback that might not run if the method + /// taking it can complete synchronously. Thus, if after passing the + /// CompletionCallback to a Pepper method, the method does not return + /// PP_OK_COMPLETIONPENDING, then you should manually call the + /// CompletionCallback's Run method, or memory will be leaked. + /// + /// @param[in] method The method to be invoked upon completion of the + /// operation. + /// + /// @return A CompletionCallback. + template + CompletionCallback NewOptionalCallback(Method method) { + CompletionCallback cc = NewCallback(method); + cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); + return cc; + } + + /// NewCallback() allocates a new, single-use CompletionCallback. + /// The CompletionCallback must be run in order for the memory + /// allocated by the methods to be freed. + /// NewCallback() is equivalent to NewRequiredCallback() below. + /// + /// @param[in] method The method to be invoked upon completion of the + /// operation. Method should be of type: + /// void (T::*)(int32_t result, const A& a) + /// + /// @param[in] a Passed to method when the completion callback + /// runs. + /// + /// @return A CompletionCallback. + template + CompletionCallback NewCallback(Method method, const A& a) { + PP_DCHECK(object_); + return NewCallbackHelper(Dispatcher1(method, a)); + } + + /// NewRequiredCallback() allocates a new, single-use + /// CompletionCallback that will always run. The + /// CompletionCallback must be run in order for the memory + /// allocated by the methods to be freed. + /// + /// @param[in] method The method to be invoked upon completion of the + /// operation. Method should be of type: + /// void (T::*)(int32_t result, const A& a) + /// + /// @param[in] a Passed to method when the completion callback + /// runs. + /// + /// @return A CompletionCallback. + template + CompletionCallback NewRequiredCallback(Method method, const A& a) { + CompletionCallback cc = NewCallback(method, a); + cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); + return cc; + } + + /// NewOptionalCallback() allocates a new, single-use + /// CompletionCallback that might not run if the method + /// taking it can complete synchronously. Thus, if after passing the + /// CompletionCallback to a Pepper method, the method does not return + /// PP_OK_COMPLETIONPENDING, then you should manually call the + /// CompletionCallback's Run method, or memory will be leaked. + /// + /// @param[in] method The method to be invoked upon completion of the + /// operation. Method should be of type: + /// void (T::*)(int32_t result, const A& a) + /// + /// @param[in] a Passed to method when the completion callback + /// runs. + /// + /// @return A CompletionCallback. + template + CompletionCallback NewOptionalCallback(Method method, const A& a) { + CompletionCallback cc = NewCallback(method, a); + cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); + return cc; + } + + /// NewCallback() allocates a new, single-use + /// CompletionCallback. + /// The CompletionCallback must be run in order for the memory + /// allocated by the methods to be freed. + /// NewCallback() is equivalent to NewRequiredCallback() below. + /// + /// @param method The method taking the callback. Method should be of type: + /// void (T::*)(int32_t result, const A& a, const B& b) + /// + /// @param[in] a Passed to method when the completion callback + /// runs. + /// + /// @param[in] b Passed to method when the completion callback + /// runs. + /// + /// @return A CompletionCallback. + template + CompletionCallback NewCallback(Method method, const A& a, const B& b) { + PP_DCHECK(object_); + return NewCallbackHelper(Dispatcher2(method, a, b)); + } + + /// NewRequiredCallback() allocates a new, single-use + /// CompletionCallback that will always run. The + /// CompletionCallback must be run in order for the memory + /// allocated by the methods to be freed. + /// + /// @param method The method taking the callback. Method should be of type: + /// void (T::*)(int32_t result, const A& a, const B& b) + /// + /// @param[in] a Passed to method when the completion callback + /// runs. + /// + /// @param[in] b Passed to method when the completion callback + /// runs. + /// + /// @return A CompletionCallback. + template + CompletionCallback NewRequiredCallback(Method method, const A& a, + const B& b) { + CompletionCallback cc = NewCallback(method, a, b); + cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); + return cc; + } + + /// NewOptionalCallback() allocates a new, single-use + /// CompletionCallback that might not run if the method + /// taking it can complete synchronously. Thus, if after passing the + /// CompletionCallback to a Pepper method, the method does not return + /// PP_OK_COMPLETIONPENDING, then you should manually call the + /// CompletionCallback's Run method, or memory will be leaked. + /// + /// @param[in] method The method taking the callback. Method should be of + /// type: + /// void (T::*)(int32_t result, const A& a, const B& b) + /// + /// @param[in] a Passed to method when the completion callback + /// runs. + /// + /// @param[in] b Passed to method when the completion callback + /// runs. + /// + /// @return A CompletionCallback. + template + CompletionCallback NewOptionalCallback(Method method, const A& a, + const B& b) { + CompletionCallback cc = NewCallback(method, a, b); + cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); + return cc; + } + + /// NewCallback() allocates a new, single-use + /// CompletionCallback. + /// The CompletionCallback must be run in order for the memory + /// allocated by the methods to be freed. + /// NewCallback() is equivalent to NewRequiredCallback() below. + /// + /// @param method The method taking the callback. Method should be of type: + /// + /// void (T::*)(int32_t result, const A& a, const B& b, const C& c) + /// + /// + /// @param[in] a Passed to method when the completion callback + /// runs. + /// + /// @param[in] b Passed to method when the completion callback + /// runs. + /// + /// @param[in] c Passed to method when the completion callback + /// runs. + /// + /// @return A CompletionCallback. + template + CompletionCallback NewCallback(Method method, const A& a, const B& b, + const C& c) { + PP_DCHECK(object_); + return NewCallbackHelper(Dispatcher3(method, a, b, c)); + } + + /// NewRequiredCallback() allocates a new, single-use + /// CompletionCallback that will always run. The + /// CompletionCallback must be run in order for the memory + /// allocated by the methods to be freed. + /// + /// @param method The method taking the callback. Method should be of type: + /// + /// void (T::*)(int32_t result, const A& a, const B& b, const C& c) + /// + /// + /// @param[in] a Passed to method when the completion callback + /// runs. + /// + /// @param[in] b Passed to method when the completion callback + /// runs. + /// + /// @param[in] c Passed to method when the completion callback + /// runs. + /// + /// @return A CompletionCallback. + template + CompletionCallback NewRequiredCallback(Method method, const A& a, + const B& b, const C& c) { + CompletionCallback cc = NewCallback(method, a, b, c); + cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); + return cc; + } + + /// NewOptionalCallback() allocates a new, single-use + /// CompletionCallback that might not run if the method + /// taking it can complete synchronously. Thus, if after passing the + /// CompletionCallback to a Pepper method, the method does not return + /// PP_OK_COMPLETIONPENDING, then you should manually call the + /// CompletionCallback's Run method, or memory will be leaked. + /// + /// @param[in] method The method taking the callback. Method should be of + /// type: + /// + /// void (T::*)(int32_t result, const A& a, const B& b, const C& c) + /// + /// + /// @param[in] a Passed to method when the completion callback + /// runs. + /// + /// @param[in] b Passed to method when the completion callback + /// runs. + /// + /// @param[in] c Passed to method when the completion callback + /// runs. + /// + /// @return A CompletionCallback. + template + CompletionCallback NewOptionalCallback(Method method, const A& a, + const B& b, const C& c) { + CompletionCallback cc = NewCallback(method, a, b, c); + cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); + return cc; + } + + private: + class BackPointer { + public: + typedef CompletionCallbackFactory FactoryType; + + BackPointer(FactoryType* factory) + : factory_(factory) { + } + + void AddRef() { + ref_.AddRef(); + } + + void Release() { + if (ref_.Release() == 0) + delete this; + } + + void DropFactory() { + factory_ = NULL; + } + + T* GetObject() { + return factory_ ? factory_->GetObject() : NULL; + } + + private: + RefCount ref_; + FactoryType* factory_; + }; + + template + class CallbackData { + public: + CallbackData(BackPointer* back_pointer, const Dispatcher& dispatcher) + : back_pointer_(back_pointer), + dispatcher_(dispatcher) { + back_pointer_->AddRef(); + } + + ~CallbackData() { + back_pointer_->Release(); + } + + static void Thunk(void* user_data, int32_t result) { + Self* self = static_cast(user_data); + T* object = self->back_pointer_->GetObject(); + if (object) + self->dispatcher_(object, result); + delete self; + } + + private: + typedef CallbackData Self; + BackPointer* back_pointer_; + Dispatcher dispatcher_; + }; + + template + class Dispatcher0 { + public: + Dispatcher0(Method method) : method_(method) { + } + void operator()(T* object, int32_t result) { + (object->*method_)(result); + } + private: + Method method_; + }; + + template + class Dispatcher1 { + public: + Dispatcher1(Method method, const A& a) + : method_(method), + a_(a) { + } + void operator()(T* object, int32_t result) { + (object->*method_)(result, a_); + } + private: + Method method_; + A a_; + }; + + template + class Dispatcher2 { + public: + Dispatcher2(Method method, const A& a, const B& b) + : method_(method), + a_(a), + b_(b) { + } + void operator()(T* object, int32_t result) { + (object->*method_)(result, a_, b_); + } + private: + Method method_; + A a_; + B b_; + }; + + template + class Dispatcher3 { + public: + Dispatcher3(Method method, const A& a, const B& b, const C& c) + : method_(method), + a_(a), + b_(b), + c_(c) { + } + void operator()(T* object, int32_t result) { + (object->*method_)(result, a_, b_, c_); + } + private: + Method method_; + A a_; + B b_; + C c_; + }; + + void InitBackPointer() { + back_pointer_ = new BackPointer(this); + back_pointer_->AddRef(); + } + + void ResetBackPointer() { + back_pointer_->DropFactory(); + back_pointer_->Release(); + } + + template + CompletionCallback NewCallbackHelper(const Dispatcher& dispatcher) { + PP_DCHECK(object_); // Expects a non-null object! + return CompletionCallback( + &CallbackData::Thunk, + new CallbackData(back_pointer_, dispatcher)); + } + + // Disallowed: + CompletionCallbackFactory(const CompletionCallbackFactory&); + CompletionCallbackFactory& operator=(const CompletionCallbackFactory&); + + T* object_; + BackPointer* back_pointer_; +}; + } // namespace pp #endif // PPAPI_CPP_COMPLETION_CALLBACK_H_ diff --git a/ppapi/cpp/non_thread_safe_ref_count.h b/ppapi/cpp/non_thread_safe_ref_count.h new file mode 100644 index 0000000..0844eb7 --- /dev/null +++ b/ppapi/cpp/non_thread_safe_ref_count.h @@ -0,0 +1,60 @@ +// Copyright (c) 2011 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 PPAPI_CPP_NON_THREAD_SAFE_REF_COUNT_H_ +#define PPAPI_CPP_NON_THREAD_SAFE_REF_COUNT_H_ + +#include "ppapi/cpp/core.h" +#include "ppapi/cpp/logging.h" +#include "ppapi/cpp/module.h" + +/// @file +/// This file defines the APIs for maintaining a reference counter. +namespace pp { + +/// A simple reference counter that is not thread-safe. Note: +/// in Debug mode, it checks that it is either called on the main thread, or +/// always called on another thread. +class NonThreadSafeRefCount { + public: + /// Default constructor. In debug mode, this checks that the object is being + /// created on the main thread. + NonThreadSafeRefCount() + : ref_(0) { +#ifndef NDEBUG + is_main_thread_ = Module::Get()->core()->IsMainThread(); +#endif + } + + /// Destructor. + ~NonThreadSafeRefCount() { + PP_DCHECK(is_main_thread_ == Module::Get()->core()->IsMainThread()); + } + + /// AddRef() increments the reference counter. + /// + /// @return An int32_t with the incremented reference counter. + int32_t AddRef() { + PP_DCHECK(is_main_thread_ == Module::Get()->core()->IsMainThread()); + return ++ref_; + } + + /// Release() decrements the reference counter. + /// + /// @return An int32_t with the decremeneted reference counter. + int32_t Release() { + PP_DCHECK(is_main_thread_ == Module::Get()->core()->IsMainThread()); + return --ref_; + } + + private: + int32_t ref_; +#ifndef NDEBUG + bool is_main_thread_; +#endif +}; + +} // namespace pp + +#endif // PPAPI_CPP_NON_THREAD_SAFE_REF_COUNT_H_ diff --git a/ppapi/cpp/paint_aggregator.cc b/ppapi/cpp/paint_aggregator.cc new file mode 100644 index 0000000..d0ab03e --- /dev/null +++ b/ppapi/cpp/paint_aggregator.cc @@ -0,0 +1,279 @@ +// Copyright (c) 2011 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 "ppapi/cpp/paint_aggregator.h" + +#include + +#include "ppapi/cpp/logging.h" + +// ---------------------------------------------------------------------------- +// ALGORITHM NOTES +// +// We attempt to maintain a scroll rect in the presence of invalidations that +// are contained within the scroll rect. If an invalidation crosses a scroll +// rect, then we just treat the scroll rect as an invalidation rect. +// +// For invalidations performed prior to scrolling and contained within the +// scroll rect, we offset the invalidation rects to account for the fact that +// the consumer will perform scrolling before painting. +// +// We only support scrolling along one axis at a time. A diagonal scroll will +// therefore be treated as an invalidation. +// ---------------------------------------------------------------------------- + +namespace pp { + +PaintAggregator::PaintUpdate::PaintUpdate() : has_scroll(false) {} + +PaintAggregator::PaintUpdate::~PaintUpdate() {} + +PaintAggregator::InternalPaintUpdate::InternalPaintUpdate() {} + +PaintAggregator::InternalPaintUpdate::~InternalPaintUpdate() {} + +Rect PaintAggregator::InternalPaintUpdate::GetScrollDamage() const { + // Should only be scrolling in one direction at a time. + PP_DCHECK(!(scroll_delta.x() && scroll_delta.y())); + + Rect damaged_rect; + + // Compute the region we will expose by scrolling, and paint that into a + // shared memory section. + if (scroll_delta.x()) { + int32_t dx = scroll_delta.x(); + damaged_rect.set_y(scroll_rect.y()); + damaged_rect.set_height(scroll_rect.height()); + if (dx > 0) { + damaged_rect.set_x(scroll_rect.x()); + damaged_rect.set_width(dx); + } else { + damaged_rect.set_x(scroll_rect.right() + dx); + damaged_rect.set_width(-dx); + } + } else { + int32_t dy = scroll_delta.y(); + damaged_rect.set_x(scroll_rect.x()); + damaged_rect.set_width(scroll_rect.width()); + if (dy > 0) { + damaged_rect.set_y(scroll_rect.y()); + damaged_rect.set_height(dy); + } else { + damaged_rect.set_y(scroll_rect.bottom() + dy); + damaged_rect.set_height(-dy); + } + } + + // In case the scroll offset exceeds the width/height of the scroll rect + return scroll_rect.Intersect(damaged_rect); +} + +Rect PaintAggregator::InternalPaintUpdate::GetPaintBounds() const { + Rect bounds; + for (size_t i = 0; i < paint_rects.size(); ++i) + bounds = bounds.Union(paint_rects[i]); + return bounds; +} + +PaintAggregator::PaintAggregator() + : max_redundant_paint_to_scroll_area_(0.8f), + max_paint_rects_(10) { +} + +bool PaintAggregator::HasPendingUpdate() const { + return !update_.scroll_rect.IsEmpty() || !update_.paint_rects.empty(); +} + +void PaintAggregator::ClearPendingUpdate() { + update_ = InternalPaintUpdate(); +} + +PaintAggregator::PaintUpdate PaintAggregator::GetPendingUpdate() const { + // Convert the internal paint update to the external one, which includes a + // bit more precomputed info for the caller. + PaintUpdate ret; + ret.scroll_delta = update_.scroll_delta; + ret.scroll_rect = update_.scroll_rect; + ret.has_scroll = ret.scroll_delta.x() != 0 || ret.scroll_delta.y() != 0; + + ret.paint_rects.reserve(update_.paint_rects.size() + 1); + for (size_t i = 0; i < update_.paint_rects.size(); i++) + ret.paint_rects.push_back(update_.paint_rects[i]); + + ret.paint_bounds = update_.GetPaintBounds(); + + // Also include the scroll damage (if any) in the paint rects. + if (ret.has_scroll) { + PP_Rect scroll_damage = update_.GetScrollDamage(); + ret.paint_rects.push_back(scroll_damage); + ret.paint_bounds = ret.paint_bounds.Union(scroll_damage); + } + + return ret; +} + +void PaintAggregator::InvalidateRect(const Rect& rect) { + // Combine overlapping paints using smallest bounding box. + for (size_t i = 0; i < update_.paint_rects.size(); ++i) { + const Rect& existing_rect = update_.paint_rects[i]; + if (existing_rect.Contains(rect)) // Optimize out redundancy. + return; + if (rect.Intersects(existing_rect) || rect.SharesEdgeWith(existing_rect)) { + // Re-invalidate in case the union intersects other paint rects. + Rect combined_rect = existing_rect.Union(rect); + update_.paint_rects.erase(update_.paint_rects.begin() + i); + InvalidateRect(combined_rect); + return; + } + } + + // Add a non-overlapping paint. + update_.paint_rects.push_back(rect); + + // If the new paint overlaps with a scroll, then it forces an invalidation of + // the scroll. If the new paint is contained by a scroll, then trim off the + // scroll damage to avoid redundant painting. + if (!update_.scroll_rect.IsEmpty()) { + if (ShouldInvalidateScrollRect(rect)) { + InvalidateScrollRect(); + } else if (update_.scroll_rect.Contains(rect)) { + update_.paint_rects[update_.paint_rects.size() - 1] = + rect.Subtract(update_.GetScrollDamage()); + if (update_.paint_rects[update_.paint_rects.size() - 1].IsEmpty()) + update_.paint_rects.erase(update_.paint_rects.end() - 1); + } + } + + if (update_.paint_rects.size() > max_paint_rects_) + CombinePaintRects(); +} + +void PaintAggregator::ScrollRect(const Rect& clip_rect, const Point& amount) { + // We only support scrolling along one axis at a time. + if (amount.x() != 0 && amount.y() != 0) { + InvalidateRect(clip_rect); + return; + } + + // We can only scroll one rect at a time. + if (!update_.scroll_rect.IsEmpty() && update_.scroll_rect != clip_rect) { + InvalidateRect(clip_rect); + return; + } + + // Again, we only support scrolling along one axis at a time. Make sure this + // update doesn't scroll on a different axis than any existing one. + if ((amount.x() && update_.scroll_delta.y()) || + (amount.y() && update_.scroll_delta.x())) { + InvalidateRect(clip_rect); + return; + } + + // The scroll rect is new or isn't changing (though the scroll amount may + // be changing). + update_.scroll_rect = clip_rect; + update_.scroll_delta += amount; + + // We might have just wiped out a pre-existing scroll. + if (update_.scroll_delta == Point()) { + update_.scroll_rect = Rect(); + return; + } + + // Adjust any contained paint rects and check for any overlapping paints. + for (size_t i = 0; i < update_.paint_rects.size(); ++i) { + if (update_.scroll_rect.Contains(update_.paint_rects[i])) { + update_.paint_rects[i] = ScrollPaintRect(update_.paint_rects[i], amount); + // The rect may have been scrolled out of view. + if (update_.paint_rects[i].IsEmpty()) { + update_.paint_rects.erase(update_.paint_rects.begin() + i); + i--; + } + } else if (update_.scroll_rect.Intersects(update_.paint_rects[i])) { + InvalidateScrollRect(); + return; + } + } + + // If the new scroll overlaps too much with contained paint rects, then force + // an invalidation of the scroll. + if (ShouldInvalidateScrollRect(Rect())) + InvalidateScrollRect(); +} + +Rect PaintAggregator::ScrollPaintRect(const Rect& paint_rect, + const Point& amount) const { + Rect result = paint_rect; + + result.Offset(amount); + result = update_.scroll_rect.Intersect(result); + + // Subtract out the scroll damage rect to avoid redundant painting. + return result.Subtract(update_.GetScrollDamage()); +} + +bool PaintAggregator::ShouldInvalidateScrollRect(const Rect& rect) const { + if (!rect.IsEmpty()) { + if (!update_.scroll_rect.Intersects(rect)) + return false; + + if (!update_.scroll_rect.Contains(rect)) + return true; + } + + // Check if the combined area of all contained paint rects plus this new + // rect comes too close to the area of the scroll_rect. If so, then we + // might as well invalidate the scroll rect. + + int paint_area = rect.size().GetArea(); + for (size_t i = 0; i < update_.paint_rects.size(); ++i) { + const Rect& existing_rect = update_.paint_rects[i]; + if (update_.scroll_rect.Contains(existing_rect)) + paint_area += existing_rect.size().GetArea(); + } + int scroll_area = update_.scroll_rect.size().GetArea(); + if (float(paint_area) / float(scroll_area) > max_redundant_paint_to_scroll_area_) + return true; + + return false; +} + +void PaintAggregator::InvalidateScrollRect() { + Rect scroll_rect = update_.scroll_rect; + update_.scroll_rect = Rect(); + update_.scroll_delta = Point(); + InvalidateRect(scroll_rect); +} + +void PaintAggregator::CombinePaintRects() { + // Combine paint rects down to at most two rects: one inside the scroll_rect + // and one outside the scroll_rect. If there is no scroll_rect, then just + // use the smallest bounding box for all paint rects. + // + // NOTE: This is a fairly simple algorithm. We could get fancier by only + // combining two rects to get us under the max_paint_rects limit, but if we + // reach this method then it means we're hitting a rare case, so there's no + // need to over-optimize it. + // + if (update_.scroll_rect.IsEmpty()) { + Rect bounds = update_.GetPaintBounds(); + update_.paint_rects.clear(); + update_.paint_rects.push_back(bounds); + } else { + Rect inner, outer; + for (size_t i = 0; i < update_.paint_rects.size(); ++i) { + const Rect& existing_rect = update_.paint_rects[i]; + if (update_.scroll_rect.Contains(existing_rect)) { + inner = inner.Union(existing_rect); + } else { + outer = outer.Union(existing_rect); + } + } + update_.paint_rects.clear(); + update_.paint_rects.push_back(inner); + update_.paint_rects.push_back(outer); + } +} + +} // namespace pp diff --git a/ppapi/cpp/paint_aggregator.h b/ppapi/cpp/paint_aggregator.h new file mode 100644 index 0000000..db1e04c --- /dev/null +++ b/ppapi/cpp/paint_aggregator.h @@ -0,0 +1,174 @@ +// Copyright (c) 2011 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 PPAPI_CPP_PAINT_AGGREGATOR_H_ +#define PPAPI_CPP_PAINT_AGGREGATOR_H_ + +#include +#include + +#include "ppapi/cpp/point.h" +#include "ppapi/cpp/rect.h" + +/// @file +/// This file defines the API to aggregate multiple invalidation and scroll +/// commands to produce a scroll and repaint sequence. +namespace pp { + +/// This class is responsible for aggregating multiple invalidation and scroll +/// commands to produce a scroll and repaint sequence. You can use this manually +/// to track your updates, but most applications will use the PaintManager to +/// additionally handle the necessary callbacks on top of the PaintAggregator +/// functionality. +/// +/// Refer to http://code.google.com/p/ppapi/wiki/2DPaintingModel +/// for further information. +class PaintAggregator { + public: + struct PaintUpdate { + /// Default constructor for creating an is_null() PaintUpdate + /// object. + PaintUpdate(); + + /// Destructor. + ~PaintUpdate(); + + /// True if there is a scroll applied. This indicates that the scroll delta + /// and scroll_rect are nonzero (just as a convenience). + bool has_scroll; + + /// The amount to scroll by. Either the X or Y may be nonzero to indicate a + /// scroll in that direction, but there will never be a scroll in both + /// directions at the same time (this will be converted to a paint of the + /// region instead). + /// + /// If there is no scroll, this will be (0, 0). + Point scroll_delta; + + /// The rectangle that should be scrolled by the scroll_delta. If there is + /// no scroll, this will be (0, 0, 0, 0). We only track one scroll command + /// at once. If there are multiple ones, they will be converted to + /// invalidates. + Rect scroll_rect; + + /// A list of all the individual dirty rectangles. This is an aggregated + /// list of all invalidate calls. Different rectangles may be unified to + /// produce a minimal list with no overlap that is more efficient to paint. + /// This list also contains the region exposed by any scroll command. + std::vector paint_rects; + + /// The union of all paint_rects. + Rect paint_bounds; + }; + + /// Default constructor. + PaintAggregator(); + + /// Setter function setting the max ratio of paint rect area to scroll rect + /// area that we will tolerate before downgrading the scroll into a repaint. + /// + /// If the combined area of paint rects contained within the scroll + /// rect grows too large, then we might as well just treat + /// the scroll rect as a paint rect. + /// + /// @param[in] area The max ratio of paint rect area to scroll rect area that + /// we will tolerate before downgrading the scroll into a repaint. + void set_max_redundant_paint_to_scroll_area(float area) { + max_redundant_paint_to_scroll_area_ = area; + } + + /// Setter function for setting the maximum number of paint rects. If we + /// exceed this limit, then we'll start combining paint rects (see + /// CombinePaintRects). This limiting can be important since there is + /// typically some overhead in deciding what to paint. If your module is fast + /// at doing these computations, raise this threshold, if your module is + /// slow, lower it (probably requires some tuning to find the right value). + /// + /// @param[in] max_rects The maximum number of paint rects. + void set_max_paint_rects(size_t max_rects) { + max_paint_rects_ = max_rects; + } + + /// This function determines if there is a pending update. There is a + /// PendingUpdate if InvalidateRect or ScrollRect were called and + /// ClearPendingUpdate was not called. + /// + /// @return true if there is a pending update, otherwise false. + bool HasPendingUpdate() const; + + /// This function clears a pending update. + void ClearPendingUpdate(); + + /// This function gets a pending update. + /// + /// @return A PaintUpdate containing the pending update. + PaintUpdate GetPendingUpdate() const; + + /// This function invalidates the rect so it will be repainted. + /// + /// @param[in] rect A rect to be repainted. + void InvalidateRect(const Rect& rect); + + /// This function adds a pending scroll update. + /// + /// @param[in] clip_rect The rect to scroll. + /// @param[in] amount A Point amount to scroll rect. + void ScrollRect(const Rect& clip_rect, const Point& amount); + + private: + // This structure is an internal version of PaintUpdate. It's different in + // two respects: + // + // - The scroll damange (area exposed by the scroll operation, if any) is + // maintained separately from the dirty rects generated by calling + // InvalidateRect. We need to know this distinction for some operations. + // + // - The paint bounds union is computed on the fly so we don't have to keep + // a rectangle up-to-date as we do different operations. + class InternalPaintUpdate { + public: + InternalPaintUpdate(); + ~InternalPaintUpdate(); + + // Computes the rect damaged by scrolling within |scroll_rect| by + // |scroll_delta|. This rect must be repainted. It is not included in + // paint_rects or in the rect returned by GetPaintBounds. + Rect GetScrollDamage() const; + + // Returns the smallest rect containing all paint rects, not including the + // scroll damage rect. + Rect GetPaintBounds() const; + + Point scroll_delta; + Rect scroll_rect; + + // Does not include the scroll damage rect. + std::vector paint_rects; + }; + + Rect ScrollPaintRect(const Rect& paint_rect, const Point& amount) const; + bool ShouldInvalidateScrollRect(const Rect& rect) const; + void InvalidateScrollRect(); + void CombinePaintRects(); + + InternalPaintUpdate update_; + + // If the combined area of paint rects contained within the scroll rect grows + // too large, then we might as well just treat the scroll rect as a paint + // rect. This constant sets the max ratio of paint rect area to scroll rect + // area that we will tolerate before downgrading the scroll into a repaint. + float max_redundant_paint_to_scroll_area_; + + // The maximum number of paint rects. If we exceed this limit, then we'll + // start combining paint rects (see CombinePaintRects). This limiting can be + // important since there is typically some overhead in deciding what to + // paint. If your plugin is fast at doing these computations, raise this + // threshold, if your plugin is slow, lower it (probably requires some + // tuning to find the right value). + size_t max_paint_rects_; +}; + +} // namespace pp + +#endif // PPAPI_CPP_PAINT_AGGREGATOR_H_ diff --git a/ppapi/cpp/paint_manager.cc b/ppapi/cpp/paint_manager.cc new file mode 100644 index 0000000..23f66d5 --- /dev/null +++ b/ppapi/cpp/paint_manager.cc @@ -0,0 +1,203 @@ +// Copyright (c) 2011 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 "ppapi/cpp/paint_manager.h" + +#include "ppapi/c/pp_errors.h" +#include "ppapi/cpp/instance.h" +#include "ppapi/cpp/logging.h" +#include "ppapi/cpp/module.h" + +namespace pp { + +PaintManager::PaintManager() + : instance_(NULL), + client_(NULL), + is_always_opaque_(false), + callback_factory_(NULL), + manual_callback_pending_(false), + flush_pending_(false), + has_pending_resize_(false) { + // Set the callback object outside of the initializer list to avoid a + // compiler warning about using "this" in an initializer list. + callback_factory_.Initialize(this); +} + +PaintManager::PaintManager(Instance* instance, + Client* client, + bool is_always_opaque) + : instance_(instance), + client_(client), + is_always_opaque_(is_always_opaque), + callback_factory_(NULL), + manual_callback_pending_(false), + flush_pending_(false), + has_pending_resize_(false) { + // Set the callback object outside of the initializer list to avoid a + // compiler warning about using "this" in an initializer list. + callback_factory_.Initialize(this); + + // You can not use a NULL client pointer. + PP_DCHECK(client); +} + +PaintManager::~PaintManager() { +} + +void PaintManager::Initialize(Instance* instance, + Client* client, + bool is_always_opaque) { + PP_DCHECK(!instance_ && !client_); // Can't initialize twice. + instance_ = instance; + client_ = client; + is_always_opaque_ = is_always_opaque; +} + +void PaintManager::SetSize(const Size& new_size) { + if (GetEffectiveSize() == new_size) + return; + + has_pending_resize_ = true; + pending_size_ = new_size; + + Invalidate(); +} + +void PaintManager::Invalidate() { + // You must call SetSize before using. + PP_DCHECK(!graphics_.is_null() || has_pending_resize_); + + EnsureCallbackPending(); + aggregator_.InvalidateRect(Rect(GetEffectiveSize())); +} + +void PaintManager::InvalidateRect(const Rect& rect) { + // You must call SetSize before using. + PP_DCHECK(!graphics_.is_null() || has_pending_resize_); + + // Clip the rect to the device area. + Rect clipped_rect = rect.Intersect(Rect(GetEffectiveSize())); + if (clipped_rect.IsEmpty()) + return; // Nothing to do. + + EnsureCallbackPending(); + aggregator_.InvalidateRect(clipped_rect); +} + +void PaintManager::ScrollRect(const Rect& clip_rect, const Point& amount) { + // You must call SetSize before using. + PP_DCHECK(!graphics_.is_null() || has_pending_resize_); + + EnsureCallbackPending(); + aggregator_.ScrollRect(clip_rect, amount); +} + +Size PaintManager::GetEffectiveSize() const { + return has_pending_resize_ ? pending_size_ : graphics_.size(); +} + +void PaintManager::EnsureCallbackPending() { + // The best way for us to do the next update is to get a notification that + // a previous one has completed. So if we're already waiting for one, we + // don't have to do anything differently now. + if (flush_pending_) + return; + + // If no flush is pending, we need to do a manual call to get back to the + // main thread. We may have one already pending, or we may need to schedule. + if (manual_callback_pending_) + return; + + Module::Get()->core()->CallOnMainThread( + 0, + callback_factory_.NewCallback(&PaintManager::OnManualCallbackComplete), + 0); + manual_callback_pending_ = true; +} + +void PaintManager::DoPaint() { + PP_DCHECK(aggregator_.HasPendingUpdate()); + + // Make a copy of the pending update and clear the pending update flag before + // actually painting. A plugin might cause invalidates in its Paint code, and + // we want those to go to the *next* paint. + PaintAggregator::PaintUpdate update = aggregator_.GetPendingUpdate(); + aggregator_.ClearPendingUpdate(); + + // Apply any pending resize. Setting the graphics to this class must happen + // before asking the plugin to paint in case it requests the Graphics2D during + // painting. However, the bind must not happen until afterward since we don't + // want to have an unpainted device bound. The needs_binding flag tells us + // whether to do this later. + bool needs_binding = false; + if (has_pending_resize_) { + graphics_ = Graphics2D(instance_, pending_size_, is_always_opaque_); + needs_binding = true; + + // Since we're binding a new one, all of the callbacks have been canceled. + manual_callback_pending_ = false; + flush_pending_ = false; + callback_factory_.CancelAll(); + + // This must be cleared before calling into the plugin since it may do + // additional invalidation or sizing operations. + has_pending_resize_ = false; + pending_size_ = Size(); + } + + // Apply any scroll before asking the client to paint. + if (update.has_scroll) + graphics_.Scroll(update.scroll_rect, update.scroll_delta); + + if (client_->OnPaint(graphics_, update.paint_rects, update.paint_bounds)) { + // Something was painted, schedule a flush. + int32_t result = graphics_.Flush( + callback_factory_.NewOptionalCallback(&PaintManager::OnFlushComplete)); + + // If you trigger this assertion, then your plugin has called Flush() + // manually. When using the PaintManager, you should not call Flush, it + // will handle that for you because it needs to know when it can do the + // next paint by implementing the flush callback. + // + // Another possible cause of this assertion is re-using devices. If you + // use one device, swap it with another, then swap it back, we won't know + // that we've already scheduled a Flush on the first device. It's best to + // not re-use devices in this way. + PP_DCHECK(result != PP_ERROR_INPROGRESS); + + if (result == PP_OK_COMPLETIONPENDING) { + flush_pending_ = true; + } else { + PP_DCHECK(result == PP_OK); // Catch all other errors in debug mode. + } + } + + if (needs_binding) + instance_->BindGraphics(graphics_); +} + +void PaintManager::OnFlushComplete(int32_t) { + PP_DCHECK(flush_pending_); + flush_pending_ = false; + + // If more paints were enqueued while we were waiting for the flush to + // complete, execute them now. + if (aggregator_.HasPendingUpdate()) + DoPaint(); +} + +void PaintManager::OnManualCallbackComplete(int32_t) { + PP_DCHECK(manual_callback_pending_); + manual_callback_pending_ = false; + + // Just because we have a manual callback doesn't mean there are actually any + // invalid regions. Even though we only schedule this callback when something + // is pending, a Flush callback could have come in before this callback was + // executed and that could have cleared the queue. + if (aggregator_.HasPendingUpdate() && !flush_pending_) + DoPaint(); +} + + +} // namespace pp diff --git a/ppapi/cpp/paint_manager.h b/ppapi/cpp/paint_manager.h new file mode 100644 index 0000000..fbddd9f --- /dev/null +++ b/ppapi/cpp/paint_manager.h @@ -0,0 +1,297 @@ +// Copyright (c) 2011 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 PPAPI_CPP_PAINT_MANAGER_H_ +#define PPAPI_CPP_PAINT_MANAGER_H_ + +#include + +#include "ppapi/cpp/completion_callback.h" +#include "ppapi/cpp/graphics_2d.h" +#include "ppapi/cpp/paint_aggregator.h" + +/// @file +/// This file defines the API to convert the "plugin push" model of painting +/// in PPAPI to a paint request at a later time. + +namespace pp { + +class Graphics2D; +class Instance; +class Point; +class Rect; + +/// This class converts the "instance push" model of painting in PPAPI to a +/// paint request at a later time. Usage is that you call Invalidate and +/// Scroll, and implement the Client interface. Your OnPaint handler will +/// then get called with coalesced paint events. +/// +/// This class is basically a PaintAggregator that groups updates, +/// plus management of callbacks for scheduling paints. +/// +/// Example: +/// +/// +/// +/// class MyClass : public pp::Instance, public PaintManager::Client { +/// public: +/// MyClass() { +/// paint_manager_.Initialize(this, this, false); +/// } +/// +/// void ViewChanged(const pp::Rect& position, const pp::Rect& clip) { +/// paint_manager_.SetSize(position.size()); +/// } +/// +/// void DoSomething() { +/// // This function does something like respond to an event that causes +/// // the screen to need updating. +/// paint_manager_.InvalidateRect(some_rect); +/// } +/// +/// // Implementation of PaintManager::Client +/// virtual bool OnPaint(pp::Graphics2D& device, +/// const pp::PaintUpdate& update) { +/// // If our app needed scrolling, we would apply that first here. +/// +/// // Then we would either repaint the area returned by GetPaintBounds or +/// // iterate through all the paint_rects. +/// +/// // The caller will call Flush() for us, so don't do that here. +/// return true; +/// } +/// +/// private: +/// pp::PaintManager paint_manager_; +/// }; +/// +class PaintManager { + public: + class Client { + public: + /// OnPaint() paints the given invalid area of the instance to the given + /// graphics device. Returns true if anything was painted. + /// + /// You are given the list of rects to paint in paint_rects, + /// and the union of all of these rects in paint_bounds. You + /// only have to paint the area inside each of the + /// paint_rects, but can paint more if you want (some apps may + /// just want to paint the union). + /// + /// Do not call Flush() on the graphics device, this will be done + /// automatically if you return true from this function since the + /// PaintManager needs to handle the callback. + /// + /// It is legal for you to cause invalidates inside of Paint which will + /// then get executed as soon as the Flush for this update has completed. + /// However, this is not very nice to the host system since it will spin the + /// CPU, possibly updating much faster than necessary. It is best to have a + /// 1/60 second timer to do an invalidate instead. This will limit your + /// animation to the slower of 60Hz or "however fast Flush can complete." + /// + /// @param[in] graphics A Graphics2D to be painted. + /// @param[in] paint_rects A list of rects to paint. + /// @param[in] paint_bounds A union of the rects to paint. + /// + /// @return true if successful, otherwise false. + virtual bool OnPaint(Graphics2D& graphics, + const std::vector& paint_rects, + const Rect& paint_bounds) = 0; + + protected: + // You shouldn't be doing deleting through this interface. + virtual ~Client() {} + }; + + /// Default constructor for creating an is_null() PaintManager + /// object. If you use this version of the constructor, you must call + /// Initialize() below. + PaintManager(); + + /// A constructor to create a new PaintManager with an instance + /// and client. + /// + /// Note: You will need to call SetSize() before this class + /// will do anything. Normally you do this from the ViewChanged + /// method of your instance. + /// + /// @param instance The instance using this paint manager to do its + /// painting. Painting will automatically go to this instance and you don't + /// have to manually bind any device context (this is all handled by the + /// paint manager). + /// + /// @param client A non-owning pointer and must remain valid (normally the + /// object implementing the Client interface will own the paint manager). + /// + /// @param is_always_opaque A flag passed to the device contexts that this + /// class creates. Set this to true if your instance always draws an opaque + /// image to the device. This is used as a hint to the browser that it does + /// not need to do alpha blending, which speeds up painting. If you generate + /// non-opqaue pixels or aren't sure, set this to false for more general + /// blending. + /// + /// If you set is_always_opaque, your alpha channel should always be set to + /// 0xFF or there may be painting artifacts. Being opaque will allow the + /// browser to do a memcpy rather than a blend to paint the plugin, and this + /// means your alpha values will get set on the page backing store. If these + /// values are incorrect, it could mess up future blending. If you aren't + /// sure, it is always correct to specify that it it not opaque. + PaintManager(Instance* instance, Client* client, bool is_always_opaque); + + /// Destructor. + ~PaintManager(); + + /// Initialize() must be called if you are using the 0-arg constructor. + /// + /// @param instance The instance using this paint manager to do its + /// painting. Painting will automatically go to this instance and you don't + /// have to manually bind any device context (this is all handled by the + /// paint manager). + /// @param client A non-owning pointer and must remain valid (normally the + /// object implementing the Client interface will own the paint manager). + /// @param is_always_opaque A flag passed to the device contexts that this + /// class creates. Set this to true if your instance always draws an opaque + /// image to the device. This is used as a hint to the browser that it does + /// not need to do alpha blending, which speeds up painting. If you generate + /// non-opqaue pixels or aren't sure, set this to false for more general + /// blending. + /// + /// If you set is_always_opaque, your alpha channel should + /// always be set to 0xFF or there may be painting artifacts. + /// Being opaque will allow the browser to do a memcpy rather than a blend + /// to paint the plugin, and this means your alpha values will get set on the + /// page backing store. If these values are incorrect, it could mess up + /// future blending. If you aren't sure, it is always correct to specify that + /// it it not opaque. + void Initialize(Instance* instance, Client* client, bool is_always_opaque); + + /// Setter function setting the max ratio of paint rect area to scroll rect + /// area that we will tolerate before downgrading the scroll into a repaint. + /// + /// If the combined area of paint rects contained within the scroll + /// rect grows too large, then we might as well just treat + /// the scroll rect as a paint rect. + /// + /// @param[in] area The max ratio of paint rect area to scroll rect area that + /// we will tolerate before downgrading the scroll into a repaint. + void set_max_redundant_paint_to_scroll_area(float area) { + aggregator_.set_max_redundant_paint_to_scroll_area(area); + } + + /// Setter function for setting the maximum number of paint rects. If we + /// exceed this limit, then we'll start combining paint rects (refer to + /// CombinePaintRects() for further information). This limiting can be + /// important since there is typically some overhead in deciding what to + /// paint. If your module is fast at doing these computations, raise this + /// threshold, if your module is slow, lower it (probably requires some + /// tuning to find the right value). + /// + /// @param[in] max_rects The maximum number of paint rects. + void set_max_paint_rects(size_t max_rects) { + aggregator_.set_max_paint_rects(max_rects); + } + + /// SetSize() sets the size of the instance. If the size is the same as the + /// previous call, this will be a NOP. If the size has changed, a new device + /// will be allocated to the given size and a paint to that device will be + /// scheduled. + /// + /// This function is intended to be called from ViewChanged with + /// the size of the instance. Since it tracks the old size and only allocates + /// when the size changes, you can always call this function without worrying + /// about whether the size changed or ViewChanged() is called for another + /// reason (like the position changed). + /// + /// @param new_size The new size for the instance. + void SetSize(const Size& new_size); + + /// This function provides access to the underlying device in case you need + /// it. If you have done a SetSize(), note that the graphics context won't be + /// updated until right before the next call to OnPaint(). + /// + /// Note: If you call Flush on this device the paint manager + /// will get very confused, don't do this! + const Graphics2D& graphics() const { return graphics_; } + + /// This function provides access to the underlying device in case you need + /// it. If you have done a SetSize(), note that the graphics context won't be + /// updated until right before the next call to OnPaint(). + /// + /// Note: If you call Flush on this device the paint manager + /// will get very confused, don't do this! + Graphics2D& graphics() { return graphics_; } + + /// Invalidate() invalidate the entire instance. + void Invalidate(); + + /// InvalidateRect() Invalidate the provided rect. + /// + /// @param[in] rect The Rect to be invalidated. + void InvalidateRect(const Rect& rect); + + /// ScrollRect() scrolls the provided clip_rect by the + /// amount argument. + /// + /// @param clip_rect The clip rectangle to scroll. + /// @param amount The amount to scroll clip_rect. + void ScrollRect(const Rect& clip_rect, const Point& amount); + + /// GetEffectiveSize() returns the size of the graphics context for the + /// next paint operation. This is the pending size if a resize is pending + /// (the instance has called SetSize() but we haven't actually painted it + /// yet), or the current size of no resize is pending. + /// + /// @return The effective size. + Size GetEffectiveSize() const; + + private: + // Disallow copy and assign (these are unimplemented). + PaintManager(const PaintManager&); + PaintManager& operator=(const PaintManager&); + + // Makes sure there is a callback that will trigger a paint at a later time. + // This will be either a Flush callback telling us we're allowed to generate + // more data, or, if there's no flush callback pending, a manual call back + // to the message loop via ExecuteOnMainThread. + void EnsureCallbackPending(); + + // Does the client paint and executes a Flush if necessary. + void DoPaint(); + + // Callback for asynchronous completion of Flush. + void OnFlushComplete(int32_t); + + // Callback for manual scheduling of paints when there is no flush callback + // pending. + void OnManualCallbackComplete(int32_t); + + Instance* instance_; + + // Non-owning pointer. See the constructor. + Client* client_; + + bool is_always_opaque_; + + CompletionCallbackFactory callback_factory_; + + // This graphics device will be is_null() if no graphics has been manually + // set yet. + Graphics2D graphics_; + + PaintAggregator aggregator_; + + // See comment for EnsureCallbackPending for more on how these work. + bool manual_callback_pending_; + bool flush_pending_; + + // When we get a resize, we don't bind right away (see SetSize). The + // has_pending_resize_ tells us that we need to do a resize for the next + // paint operation. When true, the new size is in pending_size_. + bool has_pending_resize_; + Size pending_size_; +}; + +} // namespace pp + +#endif // PPAPI_CPP_PAINT_MANAGER_H_ diff --git a/ppapi/example/example.cc b/ppapi/example/example.cc index 6ba7983..72ca3ac 100644 --- a/ppapi/example/example.cc +++ b/ppapi/example/example.cc @@ -32,7 +32,6 @@ #include "ppapi/cpp/url_request_info.h" #include "ppapi/cpp/var.h" #include "ppapi/cpp/view.h" -#include "ppapi/utility/completion_callback_factory.h" static const int kStepsPerCircle = 800; diff --git a/ppapi/examples/2d/paint_manager_example.cc b/ppapi/examples/2d/paint_manager_example.cc index d3530cb..fdf5a8b 100644 --- a/ppapi/examples/2d/paint_manager_example.cc +++ b/ppapi/examples/2d/paint_manager_example.cc @@ -8,8 +8,8 @@ #include "ppapi/cpp/input_event.h" #include "ppapi/cpp/instance.h" #include "ppapi/cpp/module.h" +#include "ppapi/cpp/paint_manager.h" #include "ppapi/cpp/size.h" -#include "ppapi/utility/graphics/paint_manager.h" // Number of pixels to each side of the center of the square that we draw. static const int kSquareRadius = 2; diff --git a/ppapi/examples/2d/scroll.cc b/ppapi/examples/2d/scroll.cc index 5dffa57..f8c365a 100644 --- a/ppapi/examples/2d/scroll.cc +++ b/ppapi/examples/2d/scroll.cc @@ -4,14 +4,14 @@ #include +#include "ppapi/cpp/completion_callback.h" #include "ppapi/cpp/graphics_2d.h" #include "ppapi/cpp/image_data.h" #include "ppapi/cpp/instance.h" #include "ppapi/cpp/module.h" +#include "ppapi/cpp/paint_manager.h" #include "ppapi/cpp/rect.h" #include "ppapi/cpp/var.h" -#include "ppapi/utility/completion_callback_factory.h" -#include "ppapi/utility/graphics/paint_manager.h" static const int kSquareSpacing = 98; static const int kSquareSize = 5; diff --git a/ppapi/examples/audio_input/audio_input.cc b/ppapi/examples/audio_input/audio_input.cc index 74bc08e..13b1237 100644 --- a/ppapi/examples/audio_input/audio_input.cc +++ b/ppapi/examples/audio_input/audio_input.cc @@ -8,6 +8,7 @@ #include #include "ppapi/cpp/audio_config.h" +#include "ppapi/cpp/completion_callback.h" #include "ppapi/cpp/dev/audio_input_dev.h" #include "ppapi/cpp/graphics_2d.h" #include "ppapi/cpp/image_data.h" @@ -16,7 +17,6 @@ #include "ppapi/cpp/module.h" #include "ppapi/cpp/rect.h" #include "ppapi/cpp/size.h" -#include "ppapi/utility/completion_callback_factory.h" class MyInstance : public pp::Instance { public: diff --git a/ppapi/examples/file_chooser/file_chooser.cc b/ppapi/examples/file_chooser/file_chooser.cc index 136ff31..8c2e675 100644 --- a/ppapi/examples/file_chooser/file_chooser.cc +++ b/ppapi/examples/file_chooser/file_chooser.cc @@ -11,7 +11,6 @@ #include "ppapi/cpp/module.h" #include "ppapi/cpp/private/instance_private.h" #include "ppapi/cpp/private/var_private.h" -#include "ppapi/utility/completion_callback_factory.h" class MyInstance : public pp::InstancePrivate { public: diff --git a/ppapi/examples/gles2/gles2.cc b/ppapi/examples/gles2/gles2.cc index 0de2eda..220a6f4 100644 --- a/ppapi/examples/gles2/gles2.cc +++ b/ppapi/examples/gles2/gles2.cc @@ -24,7 +24,6 @@ #include "ppapi/cpp/var.h" #include "ppapi/examples/gles2/testdata.h" #include "ppapi/lib/gl/include/GLES2/gl2.h" -#include "ppapi/utility/completion_callback_factory.h" // Use assert as a poor-man's CHECK, even in non-debug mode. // Since redefines assert on every inclusion (it doesn't use diff --git a/ppapi/examples/mouse_lock/mouse_lock.cc b/ppapi/examples/mouse_lock/mouse_lock.cc index 6a934ba..68aa4ac 100644 --- a/ppapi/examples/mouse_lock/mouse_lock.cc +++ b/ppapi/examples/mouse_lock/mouse_lock.cc @@ -8,6 +8,7 @@ #include "ppapi/c/dev/ppb_console_dev.h" #include "ppapi/c/ppb_input_event.h" +#include "ppapi/cpp/completion_callback.h" #include "ppapi/cpp/graphics_2d.h" #include "ppapi/cpp/image_data.h" #include "ppapi/cpp/input_event.h" @@ -17,7 +18,6 @@ #include "ppapi/cpp/mouse_lock.h" #include "ppapi/cpp/rect.h" #include "ppapi/cpp/var.h" -#include "ppapi/utility/completion_callback_factory.h" class MyInstance : public pp::Instance, public pp::MouseLock { public: diff --git a/ppapi/examples/url_loader/streaming.cc b/ppapi/examples/url_loader/streaming.cc index b7186ae..b6df6cb 100644 --- a/ppapi/examples/url_loader/streaming.cc +++ b/ppapi/examples/url_loader/streaming.cc @@ -11,12 +11,12 @@ // URLLoader.FinishSthreamingToFile once the "Open" callback is complete, and // then call URLResponseInfo.GetBodyAsFileRef once the file stream is complete. +#include "ppapi/cpp/completion_callback.h" #include "ppapi/cpp/instance.h" #include "ppapi/cpp/module.h" #include "ppapi/cpp/url_loader.h" #include "ppapi/cpp/url_request_info.h" #include "ppapi/cpp/url_response_info.h" -#include "ppapi/utility/completion_callback_factory.h" // Buffer size for reading network data. const int kBufSize = 1024; diff --git a/ppapi/examples/video_capture/video_capture.cc b/ppapi/examples/video_capture/video_capture.cc index 63e2cb8..5d474bd 100644 --- a/ppapi/examples/video_capture/video_capture.cc +++ b/ppapi/examples/video_capture/video_capture.cc @@ -20,7 +20,6 @@ #include "ppapi/cpp/module.h" #include "ppapi/cpp/rect.h" #include "ppapi/lib/gl/include/GLES2/gl2.h" -#include "ppapi/utility/completion_callback_factory.h" // Assert |context_| isn't holding any GL Errors. Done as a macro instead of a // function to preserve line number information in the failure message. diff --git a/ppapi/native_client/src/trusted/plugin/file_downloader.h b/ppapi/native_client/src/trusted/plugin/file_downloader.h index 399db7a..a913527 100644 --- a/ppapi/native_client/src/trusted/plugin/file_downloader.h +++ b/ppapi/native_client/src/trusted/plugin/file_downloader.h @@ -11,10 +11,10 @@ #include "native_client/src/include/nacl_string.h" #include "ppapi/c/trusted/ppb_file_io_trusted.h" #include "ppapi/c/trusted/ppb_url_loader_trusted.h" +#include "ppapi/cpp/completion_callback.h" #include "ppapi/cpp/file_io.h" #include "ppapi/cpp/url_loader.h" #include "ppapi/cpp/instance.h" -#include "ppapi/utility/completion_callback_factory.h" namespace plugin { diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_resources.h b/ppapi/native_client/src/trusted/plugin/pnacl_resources.h index 2d8b356..f6d35a7 100644 --- a/ppapi/native_client/src/trusted/plugin/pnacl_resources.h +++ b/ppapi/native_client/src/trusted/plugin/pnacl_resources.h @@ -14,7 +14,8 @@ #include "native_client/src/trusted/desc/nacl_desc_wrapper.h" #include "native_client/src/trusted/plugin/delayed_callback.h" #include "native_client/src/trusted/plugin/plugin_error.h" -#include "ppapi/utility/completion_callback_factory.h" + +#include "ppapi/cpp/completion_callback.h" namespace plugin { diff --git a/ppapi/ppapi_sources.gypi b/ppapi/ppapi_sources.gypi index 69ed449..84b354d 100644 --- a/ppapi/ppapi_sources.gypi +++ b/ppapi/ppapi_sources.gypi @@ -151,6 +151,11 @@ 'cpp/module_impl.h', 'cpp/mouse_lock.cc', 'cpp/mouse_lock.h', + 'cpp/non_thread_safe_ref_count.h', + 'cpp/paint_aggregator.cc', + 'cpp/paint_aggregator.h', + 'cpp/paint_manager.cc', + 'cpp/paint_manager.h', 'cpp/point.h', 'cpp/rect.cc', 'cpp/rect.h', @@ -247,14 +252,6 @@ 'cpp/trusted/file_chooser_trusted.h', 'cpp/trusted/file_io_trusted.cc', 'cpp/trusted/file_io_trusted.h', - - # Utility sources. - 'utility/completion_callback_factory.h', - 'utility/non_thread_safe_ref_count.h', - 'utility/graphics/paint_aggregator.cc', - 'utility/graphics/paint_aggregator.h', - 'utility/graphics/paint_manager.cc', - 'utility/graphics/paint_manager.h', ], # # Common Testing source for trusted and untrusted (NaCl) pugins. diff --git a/ppapi/proxy/ppb_audio_input_proxy.h b/ppapi/proxy/ppb_audio_input_proxy.h index 5fb6637..6244e55 100644 --- a/ppapi/proxy/ppb_audio_input_proxy.h +++ b/ppapi/proxy/ppb_audio_input_proxy.h @@ -13,9 +13,9 @@ #include "ipc/ipc_platform_file.h" #include "ppapi/c/dev/ppb_audio_input_dev.h" #include "ppapi/c/ppb_audio_config.h" +#include "ppapi/cpp/completion_callback.h" #include "ppapi/proxy/interface_proxy.h" #include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" -#include "ppapi/utility/completion_callback_factory.h" struct PPB_AudioInput_Dev; diff --git a/ppapi/proxy/ppb_audio_proxy.h b/ppapi/proxy/ppb_audio_proxy.h index 590f7e7..feee8dc 100644 --- a/ppapi/proxy/ppb_audio_proxy.h +++ b/ppapi/proxy/ppb_audio_proxy.h @@ -16,9 +16,9 @@ #include "ppapi/c/pp_resource.h" #include "ppapi/c/ppb_audio.h" #include "ppapi/c/ppb_audio_config.h" +#include "ppapi/cpp/completion_callback.h" #include "ppapi/proxy/interface_proxy.h" #include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" -#include "ppapi/utility/completion_callback_factory.h" struct PPB_Audio; diff --git a/ppapi/proxy/ppb_broker_proxy.h b/ppapi/proxy/ppb_broker_proxy.h index a04903c7..d2f039a 100644 --- a/ppapi/proxy/ppb_broker_proxy.h +++ b/ppapi/proxy/ppb_broker_proxy.h @@ -8,9 +8,9 @@ #include "base/sync_socket.h" #include "ipc/ipc_platform_file.h" #include "ppapi/c/pp_instance.h" +#include "ppapi/cpp/completion_callback.h" #include "ppapi/proxy/interface_proxy.h" #include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" -#include "ppapi/utility/completion_callback_factory.h" namespace ppapi { diff --git a/ppapi/proxy/ppb_file_chooser_proxy.h b/ppapi/proxy/ppb_file_chooser_proxy.h index da45a2c..887a32b 100644 --- a/ppapi/proxy/ppb_file_chooser_proxy.h +++ b/ppapi/proxy/ppb_file_chooser_proxy.h @@ -10,10 +10,10 @@ #include "base/basictypes.h" #include "ppapi/c/pp_instance.h" +#include "ppapi/cpp/completion_callback.h" #include "ppapi/proxy/interface_proxy.h" #include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" #include "ppapi/thunk/ppb_file_chooser_api.h" -#include "ppapi/utility/completion_callback_factory.h" namespace ppapi { diff --git a/ppapi/proxy/ppb_file_io_proxy.h b/ppapi/proxy/ppb_file_io_proxy.h index 86d822c..fbc8a16 100644 --- a/ppapi/proxy/ppb_file_io_proxy.h +++ b/ppapi/proxy/ppb_file_io_proxy.h @@ -11,7 +11,6 @@ #include "ppapi/c/pp_file_info.h" #include "ppapi/proxy/interface_proxy.h" #include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" -#include "ppapi/utility/completion_callback_factory.h" namespace ppapi { diff --git a/ppapi/proxy/ppb_file_ref_proxy.h b/ppapi/proxy/ppb_file_ref_proxy.h index d15536e..c0fa23c 100644 --- a/ppapi/proxy/ppb_file_ref_proxy.h +++ b/ppapi/proxy/ppb_file_ref_proxy.h @@ -11,9 +11,9 @@ #include "ppapi/c/pp_module.h" #include "ppapi/c/pp_resource.h" #include "ppapi/c/pp_time.h" +#include "ppapi/cpp/completion_callback.h" #include "ppapi/proxy/interface_proxy.h" #include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" -#include "ppapi/utility/completion_callback_factory.h" namespace ppapi { diff --git a/ppapi/proxy/ppb_file_system_proxy.h b/ppapi/proxy/ppb_file_system_proxy.h index 86eb48e..a07b824 100644 --- a/ppapi/proxy/ppb_file_system_proxy.h +++ b/ppapi/proxy/ppb_file_system_proxy.h @@ -12,9 +12,9 @@ #include "ppapi/c/pp_resource.h" #include "ppapi/c/pp_time.h" #include "ppapi/c/ppb_file_system.h" +#include "ppapi/cpp/completion_callback.h" #include "ppapi/proxy/interface_proxy.h" #include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" -#include "ppapi/utility/completion_callback_factory.h" namespace ppapi { diff --git a/ppapi/proxy/ppb_flash_menu_proxy.h b/ppapi/proxy/ppb_flash_menu_proxy.h index f0b132e..7e72fde 100644 --- a/ppapi/proxy/ppb_flash_menu_proxy.h +++ b/ppapi/proxy/ppb_flash_menu_proxy.h @@ -7,7 +7,6 @@ #include "ppapi/proxy/interface_proxy.h" #include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" -#include "ppapi/utility/completion_callback_factory.h" struct PP_Flash_Menu; struct PP_Point; diff --git a/ppapi/proxy/ppb_flash_net_connector_proxy.h b/ppapi/proxy/ppb_flash_net_connector_proxy.h index 8d290a1..0f24466 100644 --- a/ppapi/proxy/ppb_flash_net_connector_proxy.h +++ b/ppapi/proxy/ppb_flash_net_connector_proxy.h @@ -8,9 +8,9 @@ #include "base/platform_file.h" #include "ipc/ipc_platform_file.h" #include "ppapi/c/pp_instance.h" +#include "ppapi/cpp/completion_callback.h" #include "ppapi/proxy/interface_proxy.h" #include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" -#include "ppapi/utility/completion_callback_factory.h" struct PPB_Flash_NetConnector; diff --git a/ppapi/proxy/ppb_graphics_2d_proxy.h b/ppapi/proxy/ppb_graphics_2d_proxy.h index a8227f0..2897595 100644 --- a/ppapi/proxy/ppb_graphics_2d_proxy.h +++ b/ppapi/proxy/ppb_graphics_2d_proxy.h @@ -12,10 +12,10 @@ #include "ppapi/c/pp_resource.h" #include "ppapi/c/pp_size.h" #include "ppapi/c/pp_var.h" +#include "ppapi/cpp/completion_callback.h" #include "ppapi/proxy/interface_proxy.h" #include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" #include "ppapi/shared_impl/host_resource.h" -#include "ppapi/utility/completion_callback_factory.h" struct PPB_Graphics2D; struct PP_Point; diff --git a/ppapi/proxy/ppb_graphics_3d_proxy.h b/ppapi/proxy/ppb_graphics_3d_proxy.h index b8c8d09..5a6c334 100644 --- a/ppapi/proxy/ppb_graphics_3d_proxy.h +++ b/ppapi/proxy/ppb_graphics_3d_proxy.h @@ -11,11 +11,11 @@ #include "gpu/command_buffer/common/command_buffer.h" #include "ppapi/c/pp_graphics_3d.h" #include "ppapi/c/pp_instance.h" +#include "ppapi/cpp/completion_callback.h" #include "ppapi/proxy/interface_proxy.h" #include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" #include "ppapi/shared_impl/ppb_graphics_3d_shared.h" #include "ppapi/shared_impl/resource.h" -#include "ppapi/utility/completion_callback_factory.h" namespace ppapi { diff --git a/ppapi/proxy/ppb_instance_proxy.h b/ppapi/proxy/ppb_instance_proxy.h index a88bd6f..de10f80 100644 --- a/ppapi/proxy/ppb_instance_proxy.h +++ b/ppapi/proxy/ppb_instance_proxy.h @@ -8,13 +8,13 @@ #include "ppapi/c/pp_instance.h" #include "ppapi/c/pp_resource.h" #include "ppapi/c/pp_var.h" +#include "ppapi/cpp/completion_callback.h" #include "ppapi/proxy/interface_proxy.h" #include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" #include "ppapi/shared_impl/function_group_base.h" #include "ppapi/shared_impl/host_resource.h" #include "ppapi/shared_impl/ppb_instance_shared.h" #include "ppapi/thunk/ppb_instance_api.h" -#include "ppapi/utility/completion_callback_factory.h" // Windows headers interfere with this file. #ifdef PostMessage diff --git a/ppapi/proxy/ppb_url_loader_proxy.h b/ppapi/proxy/ppb_url_loader_proxy.h index da35350..e13b1a3 100644 --- a/ppapi/proxy/ppb_url_loader_proxy.h +++ b/ppapi/proxy/ppb_url_loader_proxy.h @@ -11,10 +11,10 @@ #include "ppapi/c/pp_resource.h" #include "ppapi/c/pp_size.h" #include "ppapi/c/pp_var.h" +#include "ppapi/cpp/completion_callback.h" #include "ppapi/proxy/interface_proxy.h" #include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" #include "ppapi/shared_impl/host_resource.h" -#include "ppapi/utility/completion_callback_factory.h" struct PPB_URLLoader; struct PPB_URLLoaderTrusted; diff --git a/ppapi/proxy/ppb_video_decoder_proxy.h b/ppapi/proxy/ppb_video_decoder_proxy.h index 7461a1f..1185d16 100644 --- a/ppapi/proxy/ppb_video_decoder_proxy.h +++ b/ppapi/proxy/ppb_video_decoder_proxy.h @@ -6,11 +6,11 @@ #define PPAPI_PROXY_PPB_VIDEO_DECODER_PROXY_H_ #include "ppapi/c/pp_instance.h" +#include "ppapi/cpp/completion_callback.h" #include "ppapi/proxy/interface_proxy.h" #include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" #include "ppapi/shared_impl/ppb_video_decoder_shared.h" #include "ppapi/thunk/ppb_video_decoder_api.h" -#include "ppapi/utility/completion_callback_factory.h" namespace ppapi { namespace proxy { diff --git a/ppapi/tests/DEPS b/ppapi/tests/DEPS index e901f41..d679198 100644 --- a/ppapi/tests/DEPS +++ b/ppapi/tests/DEPS @@ -10,7 +10,6 @@ include_rules = [ "+ppapi/c", "+ppapi/cpp", "+ppapi/tests", - "+ppapi/utility", ] # checkdeps.py shouldn't check include paths for files in clang, which aren't # part of the chrome build. diff --git a/ppapi/tests/all_cpp_includes.h b/ppapi/tests/all_cpp_includes.h index 8ba62a1..ff408b0 100644 --- a/ppapi/tests/all_cpp_includes.h +++ b/ppapi/tests/all_cpp_includes.h @@ -47,6 +47,9 @@ #include "ppapi/cpp/module.h" #include "ppapi/cpp/module_impl.h" #include "ppapi/cpp/mouse_lock.h" +#include "ppapi/cpp/non_thread_safe_ref_count.h" +#include "ppapi/cpp/paint_aggregator.h" +#include "ppapi/cpp/paint_manager.h" #include "ppapi/cpp/private/flash_fullscreen.h" #include "ppapi/cpp/private/instance_private.h" #include "ppapi/cpp/point.h" @@ -57,8 +60,5 @@ #include "ppapi/cpp/url_request_info.h" #include "ppapi/cpp/url_response_info.h" #include "ppapi/cpp/var.h" -#include "ppapi/utility/graphics/paint_aggregator.h" -#include "ppapi/utility/graphics/paint_manager.h" -#include "ppapi/utility/non_thread_safe_ref_count.h" #endif // PPAPI_TESTS_ALL_CPP_INCLUDES_H_ diff --git a/ppapi/tests/test_flash.h b/ppapi/tests/test_flash.h index 7275ff5..5dfed88 100644 --- a/ppapi/tests/test_flash.h +++ b/ppapi/tests/test_flash.h @@ -7,9 +7,9 @@ #include +#include "ppapi/cpp/completion_callback.h" #include "ppapi/c/pp_stdint.h" #include "ppapi/tests/test_case.h" -#include "ppapi/utility/completion_callback_factory.h" struct PPB_Flash; diff --git a/ppapi/tests/test_paint_aggregator.cc b/ppapi/tests/test_paint_aggregator.cc index a04cff8..77e2174 100644 --- a/ppapi/tests/test_paint_aggregator.cc +++ b/ppapi/tests/test_paint_aggregator.cc @@ -4,8 +4,8 @@ #include "ppapi/tests/test_paint_aggregator.h" +#include "ppapi/cpp/paint_aggregator.h" #include "ppapi/tests/testing_instance.h" -#include "ppapi/utility/graphics/paint_aggregator.h" REGISTER_TEST_CASE(PaintAggregator); diff --git a/ppapi/tests/test_transport.cc b/ppapi/tests/test_transport.cc index 7970050..52d072e 100644 --- a/ppapi/tests/test_transport.cc +++ b/ppapi/tests/test_transport.cc @@ -13,13 +13,13 @@ #include "ppapi/c/dev/ppb_testing_dev.h" #include "ppapi/c/pp_errors.h" #include "ppapi/c/pp_macros.h" +#include "ppapi/cpp/completion_callback.h" #include "ppapi/cpp/dev/transport_dev.h" #include "ppapi/cpp/instance.h" #include "ppapi/cpp/module.h" #include "ppapi/cpp/var.h" #include "ppapi/tests/test_utils.h" #include "ppapi/tests/testing_instance.h" -#include "ppapi/utility/completion_callback_factory.h" REGISTER_TEST_CASE(Transport); diff --git a/ppapi/tests/testing_instance.h b/ppapi/tests/testing_instance.h index a112c41..397c1c7 100644 --- a/ppapi/tests/testing_instance.h +++ b/ppapi/tests/testing_instance.h @@ -7,7 +7,7 @@ #include -#include "ppapi/utility/completion_callback_factory.h" +#include "ppapi/cpp/completion_callback.h" #if defined(__native_client__) #include "ppapi/cpp/instance.h" diff --git a/ppapi/utility/DEPS b/ppapi/utility/DEPS deleted file mode 100644 index 2983acb..0000000 --- a/ppapi/utility/DEPS +++ /dev/null @@ -1,14 +0,0 @@ -# ppapi/cpp should not be dependent on other parts of chromium; it should stay -# browser-neutral as much as possible. -include_rules = [ - "-base", - "-build", - "-ipc", - "-ppapi", - "+ppapi/c", - "-ppapi/c/private", - "-ppapi/c/trusted", - "+ppapi/cpp", - "-ppapi/cpp/private", - "-ppapi/cpp/trusted", -] diff --git a/ppapi/utility/README.txt b/ppapi/utility/README.txt deleted file mode 100644 index 5b72c93..0000000 --- a/ppapi/utility/README.txt +++ /dev/null @@ -1,2 +0,0 @@ -The classes in ppapi/utility are helper classes that provide higher-level -features on top of the C++ wrappers. Using these classes is optional. diff --git a/ppapi/utility/completion_callback_factory.h b/ppapi/utility/completion_callback_factory.h deleted file mode 100644 index b656024..0000000 --- a/ppapi/utility/completion_callback_factory.h +++ /dev/null @@ -1,564 +0,0 @@ -// Copyright (c) 2011 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 PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_ -#define PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_ - -#include "ppapi/cpp/completion_callback.h" -#include "ppapi/utility/non_thread_safe_ref_count.h" - -namespace pp { - -/// CompletionCallbackFactory may be used to create CompletionCallback -/// objects that are bound to member functions. -/// -/// If a factory is destroyed, then any pending callbacks will be cancelled -/// preventing any bound member functions from being called. The CancelAll() -/// method allows pending callbacks to be cancelled without destroying the -/// factory. -/// -/// Note: CompletionCallbackFactory isn't -/// thread safe, but you can make it more thread-friendly by passing a -/// thread-safe refcounting class as the second template element. However, it -/// only guarantees safety for creating a callback from another thread, the -/// callback itself needs to execute on the same thread as the thread that -/// creates/destroys the factory. With this restriction, it is safe to create -/// the CompletionCallbackFactory on the main thread, create -/// callbacks from any thread and pass them to CallOnMainThread(). -/// -/// Example: -/// -/// @code -/// -/// class MyHandler { -/// public: -/// // If an compiler warns on following using |this| in the initializer -/// // list, use PP_ALLOW_THIS_IN_INITIALIZER_LIST macro. -/// MyHandler() : factory_(this), offset_(0) { -/// } -/// -/// void ProcessFile(const FileRef& file) { -/// CompletionCallback cc = factory_.NewRequiredCallback( -/// &MyHandler::DidOpen); -/// int32_t rv = fio_.Open(file, PP_FileOpenFlag_Read, cc); -/// CHECK(rv == PP_OK_COMPLETIONPENDING); -/// } -/// -/// private: -/// CompletionCallback NewCallback() { -/// return factory_.NewCallback(&MyHandler::DidCompleteIO); -/// } -/// -/// void DidOpen(int32_t result) { -/// if (result == PP_OK) { -/// // The file is open, and we can begin reading. -/// offset_ = 0; -/// ReadMore(); -/// } else { -/// // Failed to open the file with error given by 'result'. -/// } -/// } -/// -/// void DidRead(int32_t result) { -/// if (result > 0) { -/// // buf_ now contains 'result' number of bytes from the file. -/// ProcessBytes(buf_, result); -/// offset_ += result; -/// ReadMore(); -/// } else { -/// // Done reading (possibly with an error given by 'result'). -/// } -/// } -/// -/// void ReadMore() { -/// CompletionCallback cc = -/// factory_.NewOptionalCallback(&MyHandler::DidRead); -/// int32_t rv = fio_.Read(offset_, buf_, sizeof(buf_), -/// cc.pp_completion_callback()); -/// if (rv != PP_OK_COMPLETIONPENDING) -/// cc.Run(rv); -/// } -/// -/// void ProcessBytes(const char* bytes, int32_t length) { -/// // Do work ... -/// } -/// -/// pp::CompletionCallbackFactory factory_; -/// pp::FileIO fio_; -/// char buf_[4096]; -/// int64_t offset_; -/// }; -/// -/// @endcode -/// -template -class CompletionCallbackFactory { - public: - - /// This constructor creates a CompletionCallbackFactory - /// bound to an object. If the constructor is called without an argument, - /// the default value of NULL is used. The user then must call - /// Initialize() to initialize the object. - /// - /// param[in] object Optional parameter. An object whose member functions - /// are to be bound to CompletionCallbacks created by this - /// CompletionCallbackFactory. The default value of this - /// parameter is NULL. - explicit CompletionCallbackFactory(T* object = NULL) - : object_(object) { - InitBackPointer(); - } - - /// Destructor. - ~CompletionCallbackFactory() { - ResetBackPointer(); - } - - /// CancelAll() cancels all CompletionCallbacks allocated from - /// this factory. - void CancelAll() { - ResetBackPointer(); - InitBackPointer(); - } - /// Initialize() binds the CallbackFactory to a particular - /// object. Use this when the object is not available at - /// CallbackFactory creation, and the NULL default - /// is passed to the constructor. The object may only be initialized once, - /// either by the constructor, or by a call to Initialize(). - /// - /// @param[in] object The object whose member functions are to be bound to - /// the CompletionCallback created by this - /// CompletionCallbackFactory. - void Initialize(T* object) { - PP_DCHECK(object); - PP_DCHECK(!object_); // May only initialize once! - object_ = object; - } - - /// GetObject() returns the object that was passed at initialization to - /// Intialize(). - /// - /// @return the object passed to the constructor or Intialize(). - T* GetObject() { - return object_; - } - - /// NewCallback allocates a new, single-use CompletionCallback. - /// The CompletionCallback must be run in order for the memory - /// allocated by the methods to be freed. - /// NewCallback() is equivalent to NewRequiredCallback() below. - /// - /// @param[in] method The method to be invoked upon completion of the - /// operation. - /// - /// @return A CompletionCallback. - template - CompletionCallback NewCallback(Method method) { - PP_DCHECK(object_); - return NewCallbackHelper(Dispatcher0(method)); - } - - /// NewRequiredCallback() allocates a new, single-use - /// CompletionCallback that will always run. The - /// CompletionCallback must be run in order for the memory - /// allocated by the methods to be freed. - /// - /// @param[in] method The method to be invoked upon completion of the - /// operation. - /// - /// @return A CompletionCallback. - template - CompletionCallback NewRequiredCallback(Method method) { - CompletionCallback cc = NewCallback(method); - cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); - return cc; - } - - /// NewOptionalCallback() allocates a new, single-use - /// CompletionCallback that might not run if the method - /// taking it can complete synchronously. Thus, if after passing the - /// CompletionCallback to a Pepper method, the method does not return - /// PP_OK_COMPLETIONPENDING, then you should manually call the - /// CompletionCallback's Run method, or memory will be leaked. - /// - /// @param[in] method The method to be invoked upon completion of the - /// operation. - /// - /// @return A CompletionCallback. - template - CompletionCallback NewOptionalCallback(Method method) { - CompletionCallback cc = NewCallback(method); - cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); - return cc; - } - - /// NewCallback() allocates a new, single-use CompletionCallback. - /// The CompletionCallback must be run in order for the memory - /// allocated by the methods to be freed. - /// NewCallback() is equivalent to NewRequiredCallback() below. - /// - /// @param[in] method The method to be invoked upon completion of the - /// operation. Method should be of type: - /// void (T::*)(int32_t result, const A& a) - /// - /// @param[in] a Passed to method when the completion callback - /// runs. - /// - /// @return A CompletionCallback. - template - CompletionCallback NewCallback(Method method, const A& a) { - PP_DCHECK(object_); - return NewCallbackHelper(Dispatcher1(method, a)); - } - - /// NewRequiredCallback() allocates a new, single-use - /// CompletionCallback that will always run. The - /// CompletionCallback must be run in order for the memory - /// allocated by the methods to be freed. - /// - /// @param[in] method The method to be invoked upon completion of the - /// operation. Method should be of type: - /// void (T::*)(int32_t result, const A& a) - /// - /// @param[in] a Passed to method when the completion callback - /// runs. - /// - /// @return A CompletionCallback. - template - CompletionCallback NewRequiredCallback(Method method, const A& a) { - CompletionCallback cc = NewCallback(method, a); - cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); - return cc; - } - - /// NewOptionalCallback() allocates a new, single-use - /// CompletionCallback that might not run if the method - /// taking it can complete synchronously. Thus, if after passing the - /// CompletionCallback to a Pepper method, the method does not return - /// PP_OK_COMPLETIONPENDING, then you should manually call the - /// CompletionCallback's Run method, or memory will be leaked. - /// - /// @param[in] method The method to be invoked upon completion of the - /// operation. Method should be of type: - /// void (T::*)(int32_t result, const A& a) - /// - /// @param[in] a Passed to method when the completion callback - /// runs. - /// - /// @return A CompletionCallback. - template - CompletionCallback NewOptionalCallback(Method method, const A& a) { - CompletionCallback cc = NewCallback(method, a); - cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); - return cc; - } - - /// NewCallback() allocates a new, single-use - /// CompletionCallback. - /// The CompletionCallback must be run in order for the memory - /// allocated by the methods to be freed. - /// NewCallback() is equivalent to NewRequiredCallback() below. - /// - /// @param method The method taking the callback. Method should be of type: - /// void (T::*)(int32_t result, const A& a, const B& b) - /// - /// @param[in] a Passed to method when the completion callback - /// runs. - /// - /// @param[in] b Passed to method when the completion callback - /// runs. - /// - /// @return A CompletionCallback. - template - CompletionCallback NewCallback(Method method, const A& a, const B& b) { - PP_DCHECK(object_); - return NewCallbackHelper(Dispatcher2(method, a, b)); - } - - /// NewRequiredCallback() allocates a new, single-use - /// CompletionCallback that will always run. The - /// CompletionCallback must be run in order for the memory - /// allocated by the methods to be freed. - /// - /// @param method The method taking the callback. Method should be of type: - /// void (T::*)(int32_t result, const A& a, const B& b) - /// - /// @param[in] a Passed to method when the completion callback - /// runs. - /// - /// @param[in] b Passed to method when the completion callback - /// runs. - /// - /// @return A CompletionCallback. - template - CompletionCallback NewRequiredCallback(Method method, const A& a, - const B& b) { - CompletionCallback cc = NewCallback(method, a, b); - cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); - return cc; - } - - /// NewOptionalCallback() allocates a new, single-use - /// CompletionCallback that might not run if the method - /// taking it can complete synchronously. Thus, if after passing the - /// CompletionCallback to a Pepper method, the method does not return - /// PP_OK_COMPLETIONPENDING, then you should manually call the - /// CompletionCallback's Run method, or memory will be leaked. - /// - /// @param[in] method The method taking the callback. Method should be of - /// type: - /// void (T::*)(int32_t result, const A& a, const B& b) - /// - /// @param[in] a Passed to method when the completion callback - /// runs. - /// - /// @param[in] b Passed to method when the completion callback - /// runs. - /// - /// @return A CompletionCallback. - template - CompletionCallback NewOptionalCallback(Method method, const A& a, - const B& b) { - CompletionCallback cc = NewCallback(method, a, b); - cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); - return cc; - } - - /// NewCallback() allocates a new, single-use - /// CompletionCallback. - /// The CompletionCallback must be run in order for the memory - /// allocated by the methods to be freed. - /// NewCallback() is equivalent to NewRequiredCallback() below. - /// - /// @param method The method taking the callback. Method should be of type: - /// - /// void (T::*)(int32_t result, const A& a, const B& b, const C& c) - /// - /// - /// @param[in] a Passed to method when the completion callback - /// runs. - /// - /// @param[in] b Passed to method when the completion callback - /// runs. - /// - /// @param[in] c Passed to method when the completion callback - /// runs. - /// - /// @return A CompletionCallback. - template - CompletionCallback NewCallback(Method method, const A& a, const B& b, - const C& c) { - PP_DCHECK(object_); - return NewCallbackHelper(Dispatcher3(method, a, b, c)); - } - - /// NewRequiredCallback() allocates a new, single-use - /// CompletionCallback that will always run. The - /// CompletionCallback must be run in order for the memory - /// allocated by the methods to be freed. - /// - /// @param method The method taking the callback. Method should be of type: - /// - /// void (T::*)(int32_t result, const A& a, const B& b, const C& c) - /// - /// - /// @param[in] a Passed to method when the completion callback - /// runs. - /// - /// @param[in] b Passed to method when the completion callback - /// runs. - /// - /// @param[in] c Passed to method when the completion callback - /// runs. - /// - /// @return A CompletionCallback. - template - CompletionCallback NewRequiredCallback(Method method, const A& a, - const B& b, const C& c) { - CompletionCallback cc = NewCallback(method, a, b, c); - cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); - return cc; - } - - /// NewOptionalCallback() allocates a new, single-use - /// CompletionCallback that might not run if the method - /// taking it can complete synchronously. Thus, if after passing the - /// CompletionCallback to a Pepper method, the method does not return - /// PP_OK_COMPLETIONPENDING, then you should manually call the - /// CompletionCallback's Run method, or memory will be leaked. - /// - /// @param[in] method The method taking the callback. Method should be of - /// type: - /// - /// void (T::*)(int32_t result, const A& a, const B& b, const C& c) - /// - /// - /// @param[in] a Passed to method when the completion callback - /// runs. - /// - /// @param[in] b Passed to method when the completion callback - /// runs. - /// - /// @param[in] c Passed to method when the completion callback - /// runs. - /// - /// @return A CompletionCallback. - template - CompletionCallback NewOptionalCallback(Method method, const A& a, - const B& b, const C& c) { - CompletionCallback cc = NewCallback(method, a, b, c); - cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); - return cc; - } - - private: - class BackPointer { - public: - typedef CompletionCallbackFactory FactoryType; - - BackPointer(FactoryType* factory) - : factory_(factory) { - } - - void AddRef() { - ref_.AddRef(); - } - - void Release() { - if (ref_.Release() == 0) - delete this; - } - - void DropFactory() { - factory_ = NULL; - } - - T* GetObject() { - return factory_ ? factory_->GetObject() : NULL; - } - - private: - RefCount ref_; - FactoryType* factory_; - }; - - template - class CallbackData { - public: - CallbackData(BackPointer* back_pointer, const Dispatcher& dispatcher) - : back_pointer_(back_pointer), - dispatcher_(dispatcher) { - back_pointer_->AddRef(); - } - - ~CallbackData() { - back_pointer_->Release(); - } - - static void Thunk(void* user_data, int32_t result) { - Self* self = static_cast(user_data); - T* object = self->back_pointer_->GetObject(); - if (object) - self->dispatcher_(object, result); - delete self; - } - - private: - typedef CallbackData Self; - BackPointer* back_pointer_; - Dispatcher dispatcher_; - }; - - template - class Dispatcher0 { - public: - Dispatcher0(Method method) : method_(method) { - } - void operator()(T* object, int32_t result) { - (object->*method_)(result); - } - private: - Method method_; - }; - - template - class Dispatcher1 { - public: - Dispatcher1(Method method, const A& a) - : method_(method), - a_(a) { - } - void operator()(T* object, int32_t result) { - (object->*method_)(result, a_); - } - private: - Method method_; - A a_; - }; - - template - class Dispatcher2 { - public: - Dispatcher2(Method method, const A& a, const B& b) - : method_(method), - a_(a), - b_(b) { - } - void operator()(T* object, int32_t result) { - (object->*method_)(result, a_, b_); - } - private: - Method method_; - A a_; - B b_; - }; - - template - class Dispatcher3 { - public: - Dispatcher3(Method method, const A& a, const B& b, const C& c) - : method_(method), - a_(a), - b_(b), - c_(c) { - } - void operator()(T* object, int32_t result) { - (object->*method_)(result, a_, b_, c_); - } - private: - Method method_; - A a_; - B b_; - C c_; - }; - - void InitBackPointer() { - back_pointer_ = new BackPointer(this); - back_pointer_->AddRef(); - } - - void ResetBackPointer() { - back_pointer_->DropFactory(); - back_pointer_->Release(); - } - - template - CompletionCallback NewCallbackHelper(const Dispatcher& dispatcher) { - PP_DCHECK(object_); // Expects a non-null object! - return CompletionCallback( - &CallbackData::Thunk, - new CallbackData(back_pointer_, dispatcher)); - } - - // Disallowed: - CompletionCallbackFactory(const CompletionCallbackFactory&); - CompletionCallbackFactory& operator=(const CompletionCallbackFactory&); - - T* object_; - BackPointer* back_pointer_; -}; - -} // namespace pp - -#endif // PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_ diff --git a/ppapi/utility/graphics/paint_aggregator.cc b/ppapi/utility/graphics/paint_aggregator.cc deleted file mode 100644 index d4fc721..0000000 --- a/ppapi/utility/graphics/paint_aggregator.cc +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright (c) 2011 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 "ppapi/utility/graphics/paint_aggregator.h" - -#include - -#include "ppapi/cpp/logging.h" - -// ---------------------------------------------------------------------------- -// ALGORITHM NOTES -// -// We attempt to maintain a scroll rect in the presence of invalidations that -// are contained within the scroll rect. If an invalidation crosses a scroll -// rect, then we just treat the scroll rect as an invalidation rect. -// -// For invalidations performed prior to scrolling and contained within the -// scroll rect, we offset the invalidation rects to account for the fact that -// the consumer will perform scrolling before painting. -// -// We only support scrolling along one axis at a time. A diagonal scroll will -// therefore be treated as an invalidation. -// ---------------------------------------------------------------------------- - -namespace pp { - -PaintAggregator::PaintUpdate::PaintUpdate() : has_scroll(false) {} - -PaintAggregator::PaintUpdate::~PaintUpdate() {} - -PaintAggregator::InternalPaintUpdate::InternalPaintUpdate() {} - -PaintAggregator::InternalPaintUpdate::~InternalPaintUpdate() {} - -Rect PaintAggregator::InternalPaintUpdate::GetScrollDamage() const { - // Should only be scrolling in one direction at a time. - PP_DCHECK(!(scroll_delta.x() && scroll_delta.y())); - - Rect damaged_rect; - - // Compute the region we will expose by scrolling, and paint that into a - // shared memory section. - if (scroll_delta.x()) { - int32_t dx = scroll_delta.x(); - damaged_rect.set_y(scroll_rect.y()); - damaged_rect.set_height(scroll_rect.height()); - if (dx > 0) { - damaged_rect.set_x(scroll_rect.x()); - damaged_rect.set_width(dx); - } else { - damaged_rect.set_x(scroll_rect.right() + dx); - damaged_rect.set_width(-dx); - } - } else { - int32_t dy = scroll_delta.y(); - damaged_rect.set_x(scroll_rect.x()); - damaged_rect.set_width(scroll_rect.width()); - if (dy > 0) { - damaged_rect.set_y(scroll_rect.y()); - damaged_rect.set_height(dy); - } else { - damaged_rect.set_y(scroll_rect.bottom() + dy); - damaged_rect.set_height(-dy); - } - } - - // In case the scroll offset exceeds the width/height of the scroll rect - return scroll_rect.Intersect(damaged_rect); -} - -Rect PaintAggregator::InternalPaintUpdate::GetPaintBounds() const { - Rect bounds; - for (size_t i = 0; i < paint_rects.size(); ++i) - bounds = bounds.Union(paint_rects[i]); - return bounds; -} - -PaintAggregator::PaintAggregator() - : max_redundant_paint_to_scroll_area_(0.8f), - max_paint_rects_(10) { -} - -bool PaintAggregator::HasPendingUpdate() const { - return !update_.scroll_rect.IsEmpty() || !update_.paint_rects.empty(); -} - -void PaintAggregator::ClearPendingUpdate() { - update_ = InternalPaintUpdate(); -} - -PaintAggregator::PaintUpdate PaintAggregator::GetPendingUpdate() const { - // Convert the internal paint update to the external one, which includes a - // bit more precomputed info for the caller. - PaintUpdate ret; - ret.scroll_delta = update_.scroll_delta; - ret.scroll_rect = update_.scroll_rect; - ret.has_scroll = ret.scroll_delta.x() != 0 || ret.scroll_delta.y() != 0; - - ret.paint_rects.reserve(update_.paint_rects.size() + 1); - for (size_t i = 0; i < update_.paint_rects.size(); i++) - ret.paint_rects.push_back(update_.paint_rects[i]); - - ret.paint_bounds = update_.GetPaintBounds(); - - // Also include the scroll damage (if any) in the paint rects. - if (ret.has_scroll) { - PP_Rect scroll_damage = update_.GetScrollDamage(); - ret.paint_rects.push_back(scroll_damage); - ret.paint_bounds = ret.paint_bounds.Union(scroll_damage); - } - - return ret; -} - -void PaintAggregator::InvalidateRect(const Rect& rect) { - // Combine overlapping paints using smallest bounding box. - for (size_t i = 0; i < update_.paint_rects.size(); ++i) { - const Rect& existing_rect = update_.paint_rects[i]; - if (existing_rect.Contains(rect)) // Optimize out redundancy. - return; - if (rect.Intersects(existing_rect) || rect.SharesEdgeWith(existing_rect)) { - // Re-invalidate in case the union intersects other paint rects. - Rect combined_rect = existing_rect.Union(rect); - update_.paint_rects.erase(update_.paint_rects.begin() + i); - InvalidateRect(combined_rect); - return; - } - } - - // Add a non-overlapping paint. - update_.paint_rects.push_back(rect); - - // If the new paint overlaps with a scroll, then it forces an invalidation of - // the scroll. If the new paint is contained by a scroll, then trim off the - // scroll damage to avoid redundant painting. - if (!update_.scroll_rect.IsEmpty()) { - if (ShouldInvalidateScrollRect(rect)) { - InvalidateScrollRect(); - } else if (update_.scroll_rect.Contains(rect)) { - update_.paint_rects[update_.paint_rects.size() - 1] = - rect.Subtract(update_.GetScrollDamage()); - if (update_.paint_rects[update_.paint_rects.size() - 1].IsEmpty()) - update_.paint_rects.erase(update_.paint_rects.end() - 1); - } - } - - if (update_.paint_rects.size() > max_paint_rects_) - CombinePaintRects(); -} - -void PaintAggregator::ScrollRect(const Rect& clip_rect, const Point& amount) { - // We only support scrolling along one axis at a time. - if (amount.x() != 0 && amount.y() != 0) { - InvalidateRect(clip_rect); - return; - } - - // We can only scroll one rect at a time. - if (!update_.scroll_rect.IsEmpty() && update_.scroll_rect != clip_rect) { - InvalidateRect(clip_rect); - return; - } - - // Again, we only support scrolling along one axis at a time. Make sure this - // update doesn't scroll on a different axis than any existing one. - if ((amount.x() && update_.scroll_delta.y()) || - (amount.y() && update_.scroll_delta.x())) { - InvalidateRect(clip_rect); - return; - } - - // The scroll rect is new or isn't changing (though the scroll amount may - // be changing). - update_.scroll_rect = clip_rect; - update_.scroll_delta += amount; - - // We might have just wiped out a pre-existing scroll. - if (update_.scroll_delta == Point()) { - update_.scroll_rect = Rect(); - return; - } - - // Adjust any contained paint rects and check for any overlapping paints. - for (size_t i = 0; i < update_.paint_rects.size(); ++i) { - if (update_.scroll_rect.Contains(update_.paint_rects[i])) { - update_.paint_rects[i] = ScrollPaintRect(update_.paint_rects[i], amount); - // The rect may have been scrolled out of view. - if (update_.paint_rects[i].IsEmpty()) { - update_.paint_rects.erase(update_.paint_rects.begin() + i); - i--; - } - } else if (update_.scroll_rect.Intersects(update_.paint_rects[i])) { - InvalidateScrollRect(); - return; - } - } - - // If the new scroll overlaps too much with contained paint rects, then force - // an invalidation of the scroll. - if (ShouldInvalidateScrollRect(Rect())) - InvalidateScrollRect(); -} - -Rect PaintAggregator::ScrollPaintRect(const Rect& paint_rect, - const Point& amount) const { - Rect result = paint_rect; - - result.Offset(amount); - result = update_.scroll_rect.Intersect(result); - - // Subtract out the scroll damage rect to avoid redundant painting. - return result.Subtract(update_.GetScrollDamage()); -} - -bool PaintAggregator::ShouldInvalidateScrollRect(const Rect& rect) const { - if (!rect.IsEmpty()) { - if (!update_.scroll_rect.Intersects(rect)) - return false; - - if (!update_.scroll_rect.Contains(rect)) - return true; - } - - // Check if the combined area of all contained paint rects plus this new - // rect comes too close to the area of the scroll_rect. If so, then we - // might as well invalidate the scroll rect. - - int paint_area = rect.size().GetArea(); - for (size_t i = 0; i < update_.paint_rects.size(); ++i) { - const Rect& existing_rect = update_.paint_rects[i]; - if (update_.scroll_rect.Contains(existing_rect)) - paint_area += existing_rect.size().GetArea(); - } - int scroll_area = update_.scroll_rect.size().GetArea(); - if (float(paint_area) / float(scroll_area) > max_redundant_paint_to_scroll_area_) - return true; - - return false; -} - -void PaintAggregator::InvalidateScrollRect() { - Rect scroll_rect = update_.scroll_rect; - update_.scroll_rect = Rect(); - update_.scroll_delta = Point(); - InvalidateRect(scroll_rect); -} - -void PaintAggregator::CombinePaintRects() { - // Combine paint rects down to at most two rects: one inside the scroll_rect - // and one outside the scroll_rect. If there is no scroll_rect, then just - // use the smallest bounding box for all paint rects. - // - // NOTE: This is a fairly simple algorithm. We could get fancier by only - // combining two rects to get us under the max_paint_rects limit, but if we - // reach this method then it means we're hitting a rare case, so there's no - // need to over-optimize it. - // - if (update_.scroll_rect.IsEmpty()) { - Rect bounds = update_.GetPaintBounds(); - update_.paint_rects.clear(); - update_.paint_rects.push_back(bounds); - } else { - Rect inner, outer; - for (size_t i = 0; i < update_.paint_rects.size(); ++i) { - const Rect& existing_rect = update_.paint_rects[i]; - if (update_.scroll_rect.Contains(existing_rect)) { - inner = inner.Union(existing_rect); - } else { - outer = outer.Union(existing_rect); - } - } - update_.paint_rects.clear(); - update_.paint_rects.push_back(inner); - update_.paint_rects.push_back(outer); - } -} - -} // namespace pp diff --git a/ppapi/utility/graphics/paint_aggregator.h b/ppapi/utility/graphics/paint_aggregator.h deleted file mode 100644 index 74e24da..0000000 --- a/ppapi/utility/graphics/paint_aggregator.h +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright (c) 2011 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 PPAPI_UTILITY_GRAPHICS_PAINT_AGGREGATOR_H_ -#define PPAPI_UTILITY_GRAPHICS_PAINT_AGGREGATOR_H_ - -#include -#include - -#include "ppapi/cpp/point.h" -#include "ppapi/cpp/rect.h" - -/// @file -/// This file defines the API to aggregate multiple invalidation and scroll -/// commands to produce a scroll and repaint sequence. -namespace pp { - -/// This class is responsible for aggregating multiple invalidation and scroll -/// commands to produce a scroll and repaint sequence. You can use this manually -/// to track your updates, but most applications will use the PaintManager to -/// additionally handle the necessary callbacks on top of the PaintAggregator -/// functionality. -/// -/// Refer to http://code.google.com/p/ppapi/wiki/2DPaintingModel -/// for further information. -class PaintAggregator { - public: - struct PaintUpdate { - /// Default constructor for creating an is_null() PaintUpdate - /// object. - PaintUpdate(); - - /// Destructor. - ~PaintUpdate(); - - /// True if there is a scroll applied. This indicates that the scroll delta - /// and scroll_rect are nonzero (just as a convenience). - bool has_scroll; - - /// The amount to scroll by. Either the X or Y may be nonzero to indicate a - /// scroll in that direction, but there will never be a scroll in both - /// directions at the same time (this will be converted to a paint of the - /// region instead). - /// - /// If there is no scroll, this will be (0, 0). - Point scroll_delta; - - /// The rectangle that should be scrolled by the scroll_delta. If there is - /// no scroll, this will be (0, 0, 0, 0). We only track one scroll command - /// at once. If there are multiple ones, they will be converted to - /// invalidates. - Rect scroll_rect; - - /// A list of all the individual dirty rectangles. This is an aggregated - /// list of all invalidate calls. Different rectangles may be unified to - /// produce a minimal list with no overlap that is more efficient to paint. - /// This list also contains the region exposed by any scroll command. - std::vector paint_rects; - - /// The union of all paint_rects. - Rect paint_bounds; - }; - - /// Default constructor. - PaintAggregator(); - - /// Setter function setting the max ratio of paint rect area to scroll rect - /// area that we will tolerate before downgrading the scroll into a repaint. - /// - /// If the combined area of paint rects contained within the scroll - /// rect grows too large, then we might as well just treat - /// the scroll rect as a paint rect. - /// - /// @param[in] area The max ratio of paint rect area to scroll rect area that - /// we will tolerate before downgrading the scroll into a repaint. - void set_max_redundant_paint_to_scroll_area(float area) { - max_redundant_paint_to_scroll_area_ = area; - } - - /// Setter function for setting the maximum number of paint rects. If we - /// exceed this limit, then we'll start combining paint rects (see - /// CombinePaintRects). This limiting can be important since there is - /// typically some overhead in deciding what to paint. If your module is fast - /// at doing these computations, raise this threshold, if your module is - /// slow, lower it (probably requires some tuning to find the right value). - /// - /// @param[in] max_rects The maximum number of paint rects. - void set_max_paint_rects(size_t max_rects) { - max_paint_rects_ = max_rects; - } - - /// This function determines if there is a pending update. There is a - /// PendingUpdate if InvalidateRect or ScrollRect were called and - /// ClearPendingUpdate was not called. - /// - /// @return true if there is a pending update, otherwise false. - bool HasPendingUpdate() const; - - /// This function clears a pending update. - void ClearPendingUpdate(); - - /// This function gets a pending update. - /// - /// @return A PaintUpdate containing the pending update. - PaintUpdate GetPendingUpdate() const; - - /// This function invalidates the rect so it will be repainted. - /// - /// @param[in] rect A rect to be repainted. - void InvalidateRect(const Rect& rect); - - /// This function adds a pending scroll update. - /// - /// @param[in] clip_rect The rect to scroll. - /// @param[in] amount A Point amount to scroll rect. - void ScrollRect(const Rect& clip_rect, const Point& amount); - - private: - // This structure is an internal version of PaintUpdate. It's different in - // two respects: - // - // - The scroll damange (area exposed by the scroll operation, if any) is - // maintained separately from the dirty rects generated by calling - // InvalidateRect. We need to know this distinction for some operations. - // - // - The paint bounds union is computed on the fly so we don't have to keep - // a rectangle up-to-date as we do different operations. - class InternalPaintUpdate { - public: - InternalPaintUpdate(); - ~InternalPaintUpdate(); - - // Computes the rect damaged by scrolling within |scroll_rect| by - // |scroll_delta|. This rect must be repainted. It is not included in - // paint_rects or in the rect returned by GetPaintBounds. - Rect GetScrollDamage() const; - - // Returns the smallest rect containing all paint rects, not including the - // scroll damage rect. - Rect GetPaintBounds() const; - - Point scroll_delta; - Rect scroll_rect; - - // Does not include the scroll damage rect. - std::vector paint_rects; - }; - - Rect ScrollPaintRect(const Rect& paint_rect, const Point& amount) const; - bool ShouldInvalidateScrollRect(const Rect& rect) const; - void InvalidateScrollRect(); - void CombinePaintRects(); - - InternalPaintUpdate update_; - - // If the combined area of paint rects contained within the scroll rect grows - // too large, then we might as well just treat the scroll rect as a paint - // rect. This constant sets the max ratio of paint rect area to scroll rect - // area that we will tolerate before downgrading the scroll into a repaint. - float max_redundant_paint_to_scroll_area_; - - // The maximum number of paint rects. If we exceed this limit, then we'll - // start combining paint rects (see CombinePaintRects). This limiting can be - // important since there is typically some overhead in deciding what to - // paint. If your plugin is fast at doing these computations, raise this - // threshold, if your plugin is slow, lower it (probably requires some - // tuning to find the right value). - size_t max_paint_rects_; -}; - -} // namespace pp - -#endif // PPAPI_UTILITY_PAINT_AGGREGATOR_H_ diff --git a/ppapi/utility/graphics/paint_manager.cc b/ppapi/utility/graphics/paint_manager.cc deleted file mode 100644 index 1141ac6..0000000 --- a/ppapi/utility/graphics/paint_manager.cc +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright (c) 2011 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 "ppapi/utility/graphics/paint_manager.h" - -#include "ppapi/c/pp_errors.h" -#include "ppapi/cpp/instance.h" -#include "ppapi/cpp/logging.h" -#include "ppapi/cpp/module.h" - -namespace pp { - -PaintManager::PaintManager() - : instance_(NULL), - client_(NULL), - is_always_opaque_(false), - callback_factory_(NULL), - manual_callback_pending_(false), - flush_pending_(false), - has_pending_resize_(false) { - // Set the callback object outside of the initializer list to avoid a - // compiler warning about using "this" in an initializer list. - callback_factory_.Initialize(this); -} - -PaintManager::PaintManager(Instance* instance, - Client* client, - bool is_always_opaque) - : instance_(instance), - client_(client), - is_always_opaque_(is_always_opaque), - callback_factory_(NULL), - manual_callback_pending_(false), - flush_pending_(false), - has_pending_resize_(false) { - // Set the callback object outside of the initializer list to avoid a - // compiler warning about using "this" in an initializer list. - callback_factory_.Initialize(this); - - // You can not use a NULL client pointer. - PP_DCHECK(client); -} - -PaintManager::~PaintManager() { -} - -void PaintManager::Initialize(Instance* instance, - Client* client, - bool is_always_opaque) { - PP_DCHECK(!instance_ && !client_); // Can't initialize twice. - instance_ = instance; - client_ = client; - is_always_opaque_ = is_always_opaque; -} - -void PaintManager::SetSize(const Size& new_size) { - if (GetEffectiveSize() == new_size) - return; - - has_pending_resize_ = true; - pending_size_ = new_size; - - Invalidate(); -} - -void PaintManager::Invalidate() { - // You must call SetSize before using. - PP_DCHECK(!graphics_.is_null() || has_pending_resize_); - - EnsureCallbackPending(); - aggregator_.InvalidateRect(Rect(GetEffectiveSize())); -} - -void PaintManager::InvalidateRect(const Rect& rect) { - // You must call SetSize before using. - PP_DCHECK(!graphics_.is_null() || has_pending_resize_); - - // Clip the rect to the device area. - Rect clipped_rect = rect.Intersect(Rect(GetEffectiveSize())); - if (clipped_rect.IsEmpty()) - return; // Nothing to do. - - EnsureCallbackPending(); - aggregator_.InvalidateRect(clipped_rect); -} - -void PaintManager::ScrollRect(const Rect& clip_rect, const Point& amount) { - // You must call SetSize before using. - PP_DCHECK(!graphics_.is_null() || has_pending_resize_); - - EnsureCallbackPending(); - aggregator_.ScrollRect(clip_rect, amount); -} - -Size PaintManager::GetEffectiveSize() const { - return has_pending_resize_ ? pending_size_ : graphics_.size(); -} - -void PaintManager::EnsureCallbackPending() { - // The best way for us to do the next update is to get a notification that - // a previous one has completed. So if we're already waiting for one, we - // don't have to do anything differently now. - if (flush_pending_) - return; - - // If no flush is pending, we need to do a manual call to get back to the - // main thread. We may have one already pending, or we may need to schedule. - if (manual_callback_pending_) - return; - - Module::Get()->core()->CallOnMainThread( - 0, - callback_factory_.NewCallback(&PaintManager::OnManualCallbackComplete), - 0); - manual_callback_pending_ = true; -} - -void PaintManager::DoPaint() { - PP_DCHECK(aggregator_.HasPendingUpdate()); - - // Make a copy of the pending update and clear the pending update flag before - // actually painting. A plugin might cause invalidates in its Paint code, and - // we want those to go to the *next* paint. - PaintAggregator::PaintUpdate update = aggregator_.GetPendingUpdate(); - aggregator_.ClearPendingUpdate(); - - // Apply any pending resize. Setting the graphics to this class must happen - // before asking the plugin to paint in case it requests the Graphics2D during - // painting. However, the bind must not happen until afterward since we don't - // want to have an unpainted device bound. The needs_binding flag tells us - // whether to do this later. - bool needs_binding = false; - if (has_pending_resize_) { - graphics_ = Graphics2D(instance_, pending_size_, is_always_opaque_); - needs_binding = true; - - // Since we're binding a new one, all of the callbacks have been canceled. - manual_callback_pending_ = false; - flush_pending_ = false; - callback_factory_.CancelAll(); - - // This must be cleared before calling into the plugin since it may do - // additional invalidation or sizing operations. - has_pending_resize_ = false; - pending_size_ = Size(); - } - - // Apply any scroll before asking the client to paint. - if (update.has_scroll) - graphics_.Scroll(update.scroll_rect, update.scroll_delta); - - if (client_->OnPaint(graphics_, update.paint_rects, update.paint_bounds)) { - // Something was painted, schedule a flush. - int32_t result = graphics_.Flush( - callback_factory_.NewOptionalCallback(&PaintManager::OnFlushComplete)); - - // If you trigger this assertion, then your plugin has called Flush() - // manually. When using the PaintManager, you should not call Flush, it - // will handle that for you because it needs to know when it can do the - // next paint by implementing the flush callback. - // - // Another possible cause of this assertion is re-using devices. If you - // use one device, swap it with another, then swap it back, we won't know - // that we've already scheduled a Flush on the first device. It's best to - // not re-use devices in this way. - PP_DCHECK(result != PP_ERROR_INPROGRESS); - - if (result == PP_OK_COMPLETIONPENDING) { - flush_pending_ = true; - } else { - PP_DCHECK(result == PP_OK); // Catch all other errors in debug mode. - } - } - - if (needs_binding) - instance_->BindGraphics(graphics_); -} - -void PaintManager::OnFlushComplete(int32_t) { - PP_DCHECK(flush_pending_); - flush_pending_ = false; - - // If more paints were enqueued while we were waiting for the flush to - // complete, execute them now. - if (aggregator_.HasPendingUpdate()) - DoPaint(); -} - -void PaintManager::OnManualCallbackComplete(int32_t) { - PP_DCHECK(manual_callback_pending_); - manual_callback_pending_ = false; - - // Just because we have a manual callback doesn't mean there are actually any - // invalid regions. Even though we only schedule this callback when something - // is pending, a Flush callback could have come in before this callback was - // executed and that could have cleared the queue. - if (aggregator_.HasPendingUpdate() && !flush_pending_) - DoPaint(); -} - - -} // namespace pp diff --git a/ppapi/utility/graphics/paint_manager.h b/ppapi/utility/graphics/paint_manager.h deleted file mode 100644 index c3787e8..0000000 --- a/ppapi/utility/graphics/paint_manager.h +++ /dev/null @@ -1,297 +0,0 @@ -// Copyright (c) 2011 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 PPAPI_UTILITY_GRAPHICS_PAINT_MANAGER_H_ -#define PPAPI_UTILITY_GRAPHICS_PAINT_MANAGER_H_ - -#include - -#include "ppapi/cpp/graphics_2d.h" -#include "ppapi/utility/completion_callback_factory.h" -#include "ppapi/utility/graphics/paint_aggregator.h" - -/// @file -/// This file defines the API to convert the "plugin push" model of painting -/// in PPAPI to a paint request at a later time. - -namespace pp { - -class Graphics2D; -class Instance; -class Point; -class Rect; - -/// This class converts the "instance push" model of painting in PPAPI to a -/// paint request at a later time. Usage is that you call Invalidate and -/// Scroll, and implement the Client interface. Your OnPaint handler will -/// then get called with coalesced paint events. -/// -/// This class is basically a PaintAggregator that groups updates, -/// plus management of callbacks for scheduling paints. -/// -/// Example: -/// -/// -/// -/// class MyClass : public pp::Instance, public PaintManager::Client { -/// public: -/// MyClass() { -/// paint_manager_.Initialize(this, this, false); -/// } -/// -/// void ViewChanged(const pp::Rect& position, const pp::Rect& clip) { -/// paint_manager_.SetSize(position.size()); -/// } -/// -/// void DoSomething() { -/// // This function does something like respond to an event that causes -/// // the screen to need updating. -/// paint_manager_.InvalidateRect(some_rect); -/// } -/// -/// // Implementation of PaintManager::Client -/// virtual bool OnPaint(pp::Graphics2D& device, -/// const pp::PaintUpdate& update) { -/// // If our app needed scrolling, we would apply that first here. -/// -/// // Then we would either repaint the area returned by GetPaintBounds or -/// // iterate through all the paint_rects. -/// -/// // The caller will call Flush() for us, so don't do that here. -/// return true; -/// } -/// -/// private: -/// pp::PaintManager paint_manager_; -/// }; -/// -class PaintManager { - public: - class Client { - public: - /// OnPaint() paints the given invalid area of the instance to the given - /// graphics device. Returns true if anything was painted. - /// - /// You are given the list of rects to paint in paint_rects, - /// and the union of all of these rects in paint_bounds. You - /// only have to paint the area inside each of the - /// paint_rects, but can paint more if you want (some apps may - /// just want to paint the union). - /// - /// Do not call Flush() on the graphics device, this will be done - /// automatically if you return true from this function since the - /// PaintManager needs to handle the callback. - /// - /// It is legal for you to cause invalidates inside of Paint which will - /// then get executed as soon as the Flush for this update has completed. - /// However, this is not very nice to the host system since it will spin the - /// CPU, possibly updating much faster than necessary. It is best to have a - /// 1/60 second timer to do an invalidate instead. This will limit your - /// animation to the slower of 60Hz or "however fast Flush can complete." - /// - /// @param[in] graphics A Graphics2D to be painted. - /// @param[in] paint_rects A list of rects to paint. - /// @param[in] paint_bounds A union of the rects to paint. - /// - /// @return true if successful, otherwise false. - virtual bool OnPaint(Graphics2D& graphics, - const std::vector& paint_rects, - const Rect& paint_bounds) = 0; - - protected: - // You shouldn't be doing deleting through this interface. - virtual ~Client() {} - }; - - /// Default constructor for creating an is_null() PaintManager - /// object. If you use this version of the constructor, you must call - /// Initialize() below. - PaintManager(); - - /// A constructor to create a new PaintManager with an instance - /// and client. - /// - /// Note: You will need to call SetSize() before this class - /// will do anything. Normally you do this from the ViewChanged - /// method of your instance. - /// - /// @param instance The instance using this paint manager to do its - /// painting. Painting will automatically go to this instance and you don't - /// have to manually bind any device context (this is all handled by the - /// paint manager). - /// - /// @param client A non-owning pointer and must remain valid (normally the - /// object implementing the Client interface will own the paint manager). - /// - /// @param is_always_opaque A flag passed to the device contexts that this - /// class creates. Set this to true if your instance always draws an opaque - /// image to the device. This is used as a hint to the browser that it does - /// not need to do alpha blending, which speeds up painting. If you generate - /// non-opqaue pixels or aren't sure, set this to false for more general - /// blending. - /// - /// If you set is_always_opaque, your alpha channel should always be set to - /// 0xFF or there may be painting artifacts. Being opaque will allow the - /// browser to do a memcpy rather than a blend to paint the plugin, and this - /// means your alpha values will get set on the page backing store. If these - /// values are incorrect, it could mess up future blending. If you aren't - /// sure, it is always correct to specify that it it not opaque. - PaintManager(Instance* instance, Client* client, bool is_always_opaque); - - /// Destructor. - ~PaintManager(); - - /// Initialize() must be called if you are using the 0-arg constructor. - /// - /// @param instance The instance using this paint manager to do its - /// painting. Painting will automatically go to this instance and you don't - /// have to manually bind any device context (this is all handled by the - /// paint manager). - /// @param client A non-owning pointer and must remain valid (normally the - /// object implementing the Client interface will own the paint manager). - /// @param is_always_opaque A flag passed to the device contexts that this - /// class creates. Set this to true if your instance always draws an opaque - /// image to the device. This is used as a hint to the browser that it does - /// not need to do alpha blending, which speeds up painting. If you generate - /// non-opqaue pixels or aren't sure, set this to false for more general - /// blending. - /// - /// If you set is_always_opaque, your alpha channel should - /// always be set to 0xFF or there may be painting artifacts. - /// Being opaque will allow the browser to do a memcpy rather than a blend - /// to paint the plugin, and this means your alpha values will get set on the - /// page backing store. If these values are incorrect, it could mess up - /// future blending. If you aren't sure, it is always correct to specify that - /// it it not opaque. - void Initialize(Instance* instance, Client* client, bool is_always_opaque); - - /// Setter function setting the max ratio of paint rect area to scroll rect - /// area that we will tolerate before downgrading the scroll into a repaint. - /// - /// If the combined area of paint rects contained within the scroll - /// rect grows too large, then we might as well just treat - /// the scroll rect as a paint rect. - /// - /// @param[in] area The max ratio of paint rect area to scroll rect area that - /// we will tolerate before downgrading the scroll into a repaint. - void set_max_redundant_paint_to_scroll_area(float area) { - aggregator_.set_max_redundant_paint_to_scroll_area(area); - } - - /// Setter function for setting the maximum number of paint rects. If we - /// exceed this limit, then we'll start combining paint rects (refer to - /// CombinePaintRects() for further information). This limiting can be - /// important since there is typically some overhead in deciding what to - /// paint. If your module is fast at doing these computations, raise this - /// threshold, if your module is slow, lower it (probably requires some - /// tuning to find the right value). - /// - /// @param[in] max_rects The maximum number of paint rects. - void set_max_paint_rects(size_t max_rects) { - aggregator_.set_max_paint_rects(max_rects); - } - - /// SetSize() sets the size of the instance. If the size is the same as the - /// previous call, this will be a NOP. If the size has changed, a new device - /// will be allocated to the given size and a paint to that device will be - /// scheduled. - /// - /// This function is intended to be called from ViewChanged with - /// the size of the instance. Since it tracks the old size and only allocates - /// when the size changes, you can always call this function without worrying - /// about whether the size changed or ViewChanged() is called for another - /// reason (like the position changed). - /// - /// @param new_size The new size for the instance. - void SetSize(const Size& new_size); - - /// This function provides access to the underlying device in case you need - /// it. If you have done a SetSize(), note that the graphics context won't be - /// updated until right before the next call to OnPaint(). - /// - /// Note: If you call Flush on this device the paint manager - /// will get very confused, don't do this! - const Graphics2D& graphics() const { return graphics_; } - - /// This function provides access to the underlying device in case you need - /// it. If you have done a SetSize(), note that the graphics context won't be - /// updated until right before the next call to OnPaint(). - /// - /// Note: If you call Flush on this device the paint manager - /// will get very confused, don't do this! - Graphics2D& graphics() { return graphics_; } - - /// Invalidate() invalidate the entire instance. - void Invalidate(); - - /// InvalidateRect() Invalidate the provided rect. - /// - /// @param[in] rect The Rect to be invalidated. - void InvalidateRect(const Rect& rect); - - /// ScrollRect() scrolls the provided clip_rect by the - /// amount argument. - /// - /// @param clip_rect The clip rectangle to scroll. - /// @param amount The amount to scroll clip_rect. - void ScrollRect(const Rect& clip_rect, const Point& amount); - - /// GetEffectiveSize() returns the size of the graphics context for the - /// next paint operation. This is the pending size if a resize is pending - /// (the instance has called SetSize() but we haven't actually painted it - /// yet), or the current size of no resize is pending. - /// - /// @return The effective size. - Size GetEffectiveSize() const; - - private: - // Disallow copy and assign (these are unimplemented). - PaintManager(const PaintManager&); - PaintManager& operator=(const PaintManager&); - - // Makes sure there is a callback that will trigger a paint at a later time. - // This will be either a Flush callback telling us we're allowed to generate - // more data, or, if there's no flush callback pending, a manual call back - // to the message loop via ExecuteOnMainThread. - void EnsureCallbackPending(); - - // Does the client paint and executes a Flush if necessary. - void DoPaint(); - - // Callback for asynchronous completion of Flush. - void OnFlushComplete(int32_t); - - // Callback for manual scheduling of paints when there is no flush callback - // pending. - void OnManualCallbackComplete(int32_t); - - Instance* instance_; - - // Non-owning pointer. See the constructor. - Client* client_; - - bool is_always_opaque_; - - CompletionCallbackFactory callback_factory_; - - // This graphics device will be is_null() if no graphics has been manually - // set yet. - Graphics2D graphics_; - - PaintAggregator aggregator_; - - // See comment for EnsureCallbackPending for more on how these work. - bool manual_callback_pending_; - bool flush_pending_; - - // When we get a resize, we don't bind right away (see SetSize). The - // has_pending_resize_ tells us that we need to do a resize for the next - // paint operation. When true, the new size is in pending_size_. - bool has_pending_resize_; - Size pending_size_; -}; - -} // namespace pp - -#endif // PPAPI_UTILITY_GRAPHICS_PAINT_MANAGER_H_ diff --git a/ppapi/utility/non_thread_safe_ref_count.h b/ppapi/utility/non_thread_safe_ref_count.h deleted file mode 100644 index db00b7d..0000000 --- a/ppapi/utility/non_thread_safe_ref_count.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2011 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 PPAPI_UTILITY_NON_THREAD_SAFE_REF_COUNT_H_ -#define PPAPI_UTILITY_NON_THREAD_SAFE_REF_COUNT_H_ - -#include "ppapi/cpp/core.h" -#include "ppapi/cpp/logging.h" -#include "ppapi/cpp/module.h" - -/// @file -/// This file defines the APIs for maintaining a reference counter. -namespace pp { - -/// A simple reference counter that is not thread-safe. Note: -/// in Debug mode, it checks that it is either called on the main thread, or -/// always called on another thread. -class NonThreadSafeRefCount { - public: - /// Default constructor. In debug mode, this checks that the object is being - /// created on the main thread. - NonThreadSafeRefCount() - : ref_(0) { -#ifndef NDEBUG - is_main_thread_ = Module::Get()->core()->IsMainThread(); -#endif - } - - /// Destructor. - ~NonThreadSafeRefCount() { - PP_DCHECK(is_main_thread_ == Module::Get()->core()->IsMainThread()); - } - - /// AddRef() increments the reference counter. - /// - /// @return An int32_t with the incremented reference counter. - int32_t AddRef() { - PP_DCHECK(is_main_thread_ == Module::Get()->core()->IsMainThread()); - return ++ref_; - } - - /// Release() decrements the reference counter. - /// - /// @return An int32_t with the decremeneted reference counter. - int32_t Release() { - PP_DCHECK(is_main_thread_ == Module::Get()->core()->IsMainThread()); - return --ref_; - } - - private: - int32_t ref_; -#ifndef NDEBUG - bool is_main_thread_; -#endif -}; - -} // namespace pp - -#endif // PPAPI_UTILITY_NON_THREAD_SAFE_REF_COUNT_H_ -- cgit v1.1