// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef 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" namespace pp { class Graphics2D; class Instance; class Point; class Rect; // This class converts the "plugin 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. // // Typical usage: // // 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: // Paints the given invalid area of the plugin 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." 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() {} }; // If you use this version of the constructor, you must call Initialize() // below. PaintManager(); // The instance is the plugin 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). // // The Client is a non-owning pointer and must remain valid (normally the // object implementing the Client interface will own the paint manager). // // The is_always_opaque flag will be passed to the device contexts that this // class creates. Set this to true if your plugin 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. // // You will need to call SetSize before this class will do anything. Normally // you do this from the ViewChanged method of your plugin instance. PaintManager(Instance* instance, Client* client, bool is_always_opaque); ~PaintManager(); // You must call this function before using if you use the 0-arg constructor. // See the constructor for what these arguments mean. void Initialize(Instance* instance, Client* client, bool is_always_opaque); // Setters for the configuration settings in the paint aggregator. // See paint_aggregator.h for what these mean. void set_max_redundant_paint_to_scroll_area(float area) { aggregator_.set_max_redundant_paint_to_scroll_area(area); } void set_max_paint_rects(size_t max_rects) { aggregator_.set_max_paint_rects(max_rects); } // Sets the size of the plugin. 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 is intended to be called from ViewChanged with the size of the // plugin. 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). void SetSize(const Size& new_size); // Provides access to the underlying device in case you need it. 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_; } Graphics2D& graphics() { return graphics_; } // Invalidate the entire plugin. void Invalidate(); // Invalidate the given rect. void InvalidateRect(const Rect& rect); // The given rect should be scrolled by the given amounts. void ScrollRect(const Rect& clip_rect, const Point& amount); 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_; }; } // namespace pp #endif // PPAPI_CPP_PAINT_MANAGER_H_